├── MvpAutoCode
├── .gitignore
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── lkl
│ │ │ └── plugin
│ │ │ └── Utils.java
│ │ ├── kotlin
│ │ └── com
│ │ │ └── lkl
│ │ │ └── plugin
│ │ │ ├── Extfun.kt
│ │ │ ├── config
│ │ │ └── ItemConfigBean.kt
│ │ │ ├── Cons.kt
│ │ │ ├── maker
│ │ │ ├── ComponentRegister.kt
│ │ │ ├── CodeMaker.kt
│ │ │ ├── TemplateMaker.kt
│ │ │ └── FileMaker.kt
│ │ │ └── TemplateCons.java
│ │ └── resources
│ │ └── META-INF
│ │ └── plugin.xml
└── build.gradle
├── .gitignore
├── ComparingReferencesInspection
├── .gitignore
├── src
│ ├── test
│ │ ├── testData
│ │ │ ├── Neq.java
│ │ │ ├── Eq.after.java
│ │ │ ├── Eq.java
│ │ │ └── Neq.after.java
│ │ └── java
│ │ │ └── com
│ │ │ └── lkl
│ │ │ └── plugin
│ │ │ └── ComparingReferencesInspectionTest.java
│ └── main
│ │ └── resources
│ │ ├── inspectionDescriptions
│ │ └── ComparingReferences.html
│ │ └── META-INF
│ │ └── plugin.xml
└── build.gradle
├── IdeaPluginStudy
├── .gitignore
├── src
│ └── main
│ │ ├── java
│ │ └── com
│ │ │ └── lkl
│ │ │ └── plugin
│ │ │ ├── codegenerator
│ │ │ ├── ConflictResolutionPolicy.java
│ │ │ ├── util
│ │ │ │ ├── MemberEntry.java
│ │ │ │ ├── EntryFactory.java
│ │ │ │ └── EntryUtils.java
│ │ │ ├── config
│ │ │ │ ├── PipelineStep.java
│ │ │ │ ├── ClassSelectionConfig.java
│ │ │ │ ├── CodeTemplateList.java
│ │ │ │ ├── CodeGeneratorSettings.java
│ │ │ │ ├── CodeTemplate.java
│ │ │ │ └── MemberSelectionConfig.java
│ │ │ ├── ui
│ │ │ │ ├── PipelineStepConfig.java
│ │ │ │ ├── ClassSelectionPane.form
│ │ │ │ ├── CodeGeneratorConfigurable.java
│ │ │ │ ├── ClassSelectionPane.java
│ │ │ │ └── SelectionPane.form
│ │ │ ├── CodeGenerator.java
│ │ │ ├── worker
│ │ │ │ └── JavaCaretWorker.java
│ │ │ └── action
│ │ │ │ └── CodeGeneratorGroup.java
│ │ │ ├── tostring
│ │ │ ├── template
│ │ │ │ ├── toString
│ │ │ │ └── TemplatesState.java
│ │ │ ├── GenerateToStringInterfaceFilter.java
│ │ │ ├── GenerateToStringAction.java
│ │ │ ├── exception
│ │ │ │ └── TemplateResourceException.java
│ │ │ ├── GenerateToStringClassFilter.java
│ │ │ ├── config
│ │ │ │ ├── DuplicatePolicy.java
│ │ │ │ ├── InsertAtCaretStrategy.java
│ │ │ │ ├── ReplacePolicy.java
│ │ │ │ └── InsertAfterEqualsHashCodeStrategy.java
│ │ │ ├── element
│ │ │ │ ├── ElementComparator.java
│ │ │ │ ├── FieldElement.java
│ │ │ │ ├── GenerationHelper.java
│ │ │ │ ├── MethodElement.java
│ │ │ │ └── ElementUtils.java
│ │ │ ├── view
│ │ │ │ ├── MethodExistsDialog.java
│ │ │ │ └── TemplatesPanel.java
│ │ │ ├── GenerateToStringConfigurable.java
│ │ │ └── velocity
│ │ │ │ └── VelocityFactory.java
│ │ │ ├── base
│ │ │ ├── MyAction.java
│ │ │ ├── SecondAction.java
│ │ │ ├── MyGroup1.java
│ │ │ ├── InsertCharAction.java
│ │ │ ├── HelloWorldPlugin.java
│ │ │ ├── MyGroup.java
│ │ │ ├── MyTypedActionHandler.java
│ │ │ └── GetterAndSetter.java
│ │ │ ├── PsiAugmentProvider
│ │ │ └── CustomPsiAugmentProvider.java
│ │ │ ├── configurable
│ │ │ ├── SingleFileExecutionConfigurable.java
│ │ │ ├── SingleFileExecutionConfig.java
│ │ │ └── ExeOverwriteConfirmDialog.form
│ │ │ └── StructureViewExtension
│ │ │ └── CustomStructureViewExtension.java
│ │ └── resources
│ │ ├── template
│ │ ├── to-string.xml
│ │ ├── getters-and-setters.xml
│ │ └── default.vm
│ │ └── META-INF
│ │ └── plugin.xml
└── build.gradle
├── docs
├── base
│ ├── imgs
│ │ ├── log.png
│ │ ├── action
│ │ │ ├── openEditor.png
│ │ │ ├── closeEditor.png
│ │ │ ├── codeCreateGroup.png
│ │ │ ├── groupIdMainMenu.png
│ │ │ ├── defaultActionGroup.png
│ │ │ ├── groupActionPopupTrue.png
│ │ │ ├── groupActionPopupFalse.png
│ │ │ ├── groupIdEditorPopupMenu.png
│ │ │ └── groupIdProjectViewPopupMenu.png
│ │ ├── helloWorld
│ │ │ ├── helpMenu.png
│ │ │ ├── message.png
│ │ │ ├── welcome.png
│ │ │ ├── newPlugin1.png
│ │ │ ├── newPlugin2.png
│ │ │ ├── createAction.png
│ │ │ ├── installPlugin.png
│ │ │ ├── buildDeployment.png
│ │ │ ├── buildDeployment1.png
│ │ │ ├── projectStructure.png
│ │ │ └── uninstallPlugin.png
│ │ ├── editor
│ │ │ └── caretModelPosition.png
│ │ └── gradlePlugin
│ │ │ ├── step1_new_gradle_project.png
│ │ │ └── gradle_tasks_in_tool_window.png
│ ├── log.md
│ ├── kotlinPlugin.md
│ └── helloWorld.md
├── psi
│ ├── imgs
│ │ └── structureView.png
│ ├── structureViewExtension.md
│ └── psiAugmentProvider.md
└── advanced
│ ├── imgs
│ ├── configurable
│ │ ├── newGuiForm.png
│ │ ├── pluginConfigurationDisplay.png
│ │ └── singlefileexecutionconfigurable_setting2.png
│ └── codeInspections
│ │ ├── comparingReferences.png
│ │ └── comparingReferences_options.png
│ ├── generateTostring.md
│ └── persistStateComponent.md
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── settings.gradle
├── gradle.properties
├── README.md
└── gradlew.bat
/MvpAutoCode/.gitignore:
--------------------------------------------------------------------------------
1 | build/
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle/
2 | .idea/
3 | out/
--------------------------------------------------------------------------------
/ComparingReferencesInspection/.gitignore:
--------------------------------------------------------------------------------
1 | build/
--------------------------------------------------------------------------------
/IdeaPluginStudy/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle/
2 | .idea/
3 | out/
4 | build/
5 | IdeaPluginStudy.jar
--------------------------------------------------------------------------------
/docs/base/imgs/log.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/log.png
--------------------------------------------------------------------------------
/docs/psi/imgs/structureView.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/psi/imgs/structureView.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/docs/base/imgs/action/openEditor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/action/openEditor.png
--------------------------------------------------------------------------------
/docs/base/imgs/action/closeEditor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/action/closeEditor.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/helpMenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/helpMenu.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/message.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/welcome.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/welcome.png
--------------------------------------------------------------------------------
/docs/base/imgs/action/codeCreateGroup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/action/codeCreateGroup.png
--------------------------------------------------------------------------------
/docs/base/imgs/action/groupIdMainMenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/action/groupIdMainMenu.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/newPlugin1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/newPlugin1.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/newPlugin2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/newPlugin2.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/createAction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/createAction.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/installPlugin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/installPlugin.png
--------------------------------------------------------------------------------
/docs/advanced/imgs/configurable/newGuiForm.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/advanced/imgs/configurable/newGuiForm.png
--------------------------------------------------------------------------------
/docs/base/imgs/action/defaultActionGroup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/action/defaultActionGroup.png
--------------------------------------------------------------------------------
/docs/base/imgs/action/groupActionPopupTrue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/action/groupActionPopupTrue.png
--------------------------------------------------------------------------------
/docs/base/imgs/editor/caretModelPosition.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/editor/caretModelPosition.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/buildDeployment.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/buildDeployment.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/buildDeployment1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/buildDeployment1.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/projectStructure.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/projectStructure.png
--------------------------------------------------------------------------------
/docs/base/imgs/helloWorld/uninstallPlugin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/helloWorld/uninstallPlugin.png
--------------------------------------------------------------------------------
/docs/base/imgs/action/groupActionPopupFalse.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/action/groupActionPopupFalse.png
--------------------------------------------------------------------------------
/docs/base/imgs/action/groupIdEditorPopupMenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/action/groupIdEditorPopupMenu.png
--------------------------------------------------------------------------------
/docs/base/imgs/action/groupIdProjectViewPopupMenu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/action/groupIdProjectViewPopupMenu.png
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'IntellijPluginStudy'
2 | include 'IdeaPluginStudy'
3 | include 'MvpAutoCode'
4 | include 'ComparingReferencesInspection'
5 |
6 |
--------------------------------------------------------------------------------
/docs/base/imgs/gradlePlugin/step1_new_gradle_project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/gradlePlugin/step1_new_gradle_project.png
--------------------------------------------------------------------------------
/docs/advanced/imgs/codeInspections/comparingReferences.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/advanced/imgs/codeInspections/comparingReferences.png
--------------------------------------------------------------------------------
/docs/base/imgs/gradlePlugin/gradle_tasks_in_tool_window.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/base/imgs/gradlePlugin/gradle_tasks_in_tool_window.png
--------------------------------------------------------------------------------
/docs/advanced/imgs/configurable/pluginConfigurationDisplay.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/advanced/imgs/configurable/pluginConfigurationDisplay.png
--------------------------------------------------------------------------------
/docs/advanced/imgs/codeInspections/comparingReferences_options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/advanced/imgs/codeInspections/comparingReferences_options.png
--------------------------------------------------------------------------------
/ComparingReferencesInspection/src/test/testData/Neq.java:
--------------------------------------------------------------------------------
1 | public class Neq {
2 | public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
3 | return (dt1 != dt2);
4 | }
5 |
6 | }
--------------------------------------------------------------------------------
/docs/advanced/imgs/configurable/singlefileexecutionconfigurable_setting2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lkl22/IntellijPluginStudy/HEAD/docs/advanced/imgs/configurable/singlefileexecutionconfigurable_setting2.png
--------------------------------------------------------------------------------
/ComparingReferencesInspection/src/test/testData/Eq.after.java:
--------------------------------------------------------------------------------
1 | public class Eq {
2 | public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
3 | return (s1.equals(s2));
4 | }
5 |
6 | }
--------------------------------------------------------------------------------
/ComparingReferencesInspection/src/test/testData/Eq.java:
--------------------------------------------------------------------------------
1 | public class Eq {
2 | public boolean compare2Strings(java.lang.String s1, java.lang.String s2) {
3 | return (s1 == s2);
4 | }
5 |
6 | }
--------------------------------------------------------------------------------
/ComparingReferencesInspection/src/test/testData/Neq.after.java:
--------------------------------------------------------------------------------
1 | public class Neq {
2 | public boolean compare2Dates(java.util.Date dt1, java.util.Date dt2){
3 | return (!dt1.equals(dt2));
4 | }
5 |
6 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/ConflictResolutionPolicy.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator;
2 |
3 | public enum ConflictResolutionPolicy {
4 | CANCEL,
5 | DUPLICATE,
6 | DUPLICATE_ALL,
7 | REPLACE,
8 | REPLACE_ALL,
9 | }
10 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultGuava.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | return com.google.common.base.Objects.toStringHelper(this)
3 | #foreach ($member in $members)
4 | .add("$member.name", $member.accessor)
5 | #end
6 | .toString();
7 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultGuava18.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | return com.google.common.base.MoreObjects.toStringHelper(this)
3 | #foreach ($member in $members)
4 | .add("$member.name", $member.accessor)
5 | #end
6 | .toString();
7 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultToStringBuilder.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | return new org.apache.commons.lang.builder.ToStringBuilder(this)
3 | #foreach ($member in $members)
4 | .append("$member.name", $member.accessor)
5 | #end
6 | .toString();
7 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultToStringBuilder3.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | return new org.apache.commons.lang3.builder.ToStringBuilder(this)
3 | #foreach ($member in $members)
4 | .append("$member.name", $member.accessor)
5 | #end
6 | .toString();
7 | }
--------------------------------------------------------------------------------
/docs/advanced/generateTostring.md:
--------------------------------------------------------------------------------
1 | # generate-tostring
2 |
3 | ## 参考文献
4 |
5 | [CodeGenerator](https://github.com/lotabout/CodeGenerator)
6 |
7 | [https://github.com/JetBrains/intellij-community/tree/master/plugins/generate-tostring](https://github.com/JetBrains/intellij-community/tree/master/plugins/generate-tostring)
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/util/MemberEntry.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.util;
2 |
3 | import com.intellij.psi.PsiMember;
4 | import org.jetbrains.java.generate.element.Element;
5 |
6 | public interface MemberEntry extends Element {
7 | T getRaw();
8 | }
9 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/config/PipelineStep.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.config;
2 |
3 | public interface PipelineStep {
4 | String type();
5 | String postfix();
6 | void postfix(String postfix);
7 | boolean enabled();
8 | void enabled(boolean enabled);
9 | }
10 |
--------------------------------------------------------------------------------
/docs/base/log.md:
--------------------------------------------------------------------------------
1 | # 打印日志,查看日志
2 |
3 | ## 创建log对象
4 | ```java
5 | import com.intellij.openapi.diagnostic.Logger;
6 |
7 | protected static final Logger log = Logger.getInstance(xxx.class);
8 | ```
9 |
10 | ## 查看日志
11 |
12 | 点击`『showlog in finder』`,会打开一个目录,里面有很多的log文件,你在plugin工程中使用Logger.info打印的日志都会存储在该log文件中,打开即可
13 |
14 | 
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/ui/PipelineStepConfig.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.ui;
2 |
3 | import com.lkl.plugin.codegenerator.config.PipelineStep;
4 |
5 | import javax.swing.*;
6 |
7 | public interface PipelineStepConfig {
8 | PipelineStep getConfig();
9 | JComponent getComponent();
10 | }
11 |
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/java/com/lkl/plugin/Utils.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin;
2 |
3 | /**
4 | * Created by XQ Yang on 2018/6/25 18:14.
5 | * Description :
6 | */
7 |
8 | public class Utils {
9 | public Utils() {
10 | }
11 |
12 | public static boolean isEmpty(CharSequence s) {
13 | if (s == null) {
14 | return true;
15 | } else {
16 | return s.length() == 0;
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/kotlin/com/lkl/plugin/Extfun.kt:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin
2 |
3 | /**
4 | * Created by XQ Yang on 2018/6/25 19:17.
5 | * Description :
6 | */
7 |
8 | fun MutableSet.eAdd(vararg e: E): Set {
9 | if (e.size > 1) {
10 | this.addAll(e)
11 | } else if (e.isNotEmpty()) {
12 | this.add(e[0])
13 | }
14 | return this
15 | }
16 |
17 | fun String.lastDotContent() = this.substring(this.lastIndexOf(".") + 1, this.length)
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/kotlin/com/lkl/plugin/config/ItemConfigBean.kt:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.config
2 |
3 | import com.intellij.ide.util.PropertiesComponent
4 |
5 | /**
6 | * Created by XQ Yang on 2018/6/28 16:20.
7 | * Description :
8 | */
9 | data class ItemConfigBean(val name: String, val isJava: Boolean = true, val isActivity: Boolean = true, val vImpl: String, val pImpl: String, val mImpl: String,
10 | val state: PropertiesComponent, val generateModel: Boolean = true)
--------------------------------------------------------------------------------
/ComparingReferencesInspection/src/main/resources/inspectionDescriptions/ComparingReferences.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SDK: This inspection reports when the '==' or '!=' operator was used between expressions of
6 | reference types.
7 | Classes to be inspected are controlled by a semi-colon separated Options list in the preferences panel for this inspection.
8 |
9 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/CodeGenerator.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator;
2 |
3 | import com.intellij.openapi.components.ApplicationComponent;
4 | import org.jetbrains.annotations.NotNull;
5 |
6 | public class CodeGenerator implements ApplicationComponent {
7 | public CodeGenerator() {
8 | }
9 |
10 | @Override
11 | public void initComponent() {}
12 |
13 | @Override
14 | public void disposeComponent() {
15 | }
16 |
17 | @Override
18 | @NotNull
19 | public String getComponentName() {
20 | return "me.lotabout.codegenerator.CodeGenerator";
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/StringJoiner.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | return new java.util.StringJoiner(", ", $classname##
3 | .class.getSimpleName() + "[", "]")
4 | #foreach ($member in $members)
5 | #if(!$member.modifierStatic)
6 | .add("$member.name=##
7 | #if ($member.primitiveArray || $member.objectArray)
8 | " + java.util.Arrays.toString($member.name)##
9 | #elseif ($member.string)
10 | '" + $member.accessor + "'"##
11 | #else
12 | " + $member.accessor ##
13 | #end
14 | )
15 | #end
16 | #end
17 | .toString();
18 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/base/MyAction.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.base;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.PlatformDataKeys;
6 | import com.intellij.openapi.project.Project;
7 | import com.intellij.openapi.ui.Messages;
8 |
9 | /**
10 | * Created by likunlun on 2020/7/11.
11 | */
12 | public class MyAction extends AnAction {
13 |
14 | @Override
15 | public void actionPerformed(AnActionEvent anActionEvent) {
16 | Project project = anActionEvent.getData(PlatformDataKeys.PROJECT);
17 | Messages.showMessageDialog(project, "Hello Action!", "Information", Messages.getInformationIcon());
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/base/SecondAction.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.base;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.PlatformDataKeys;
6 | import com.intellij.openapi.project.Project;
7 | import com.intellij.openapi.ui.Messages;
8 |
9 | /**
10 | * Created by likunlun on 2020/7/11.
11 | */
12 | public class SecondAction extends AnAction {
13 |
14 | @Override
15 | public void actionPerformed(AnActionEvent anActionEvent) {
16 | Project project = anActionEvent.getData(PlatformDataKeys.PROJECT);
17 | Messages.showMessageDialog(project, "Hello Second Action!", "Information", Messages.getInformationIcon());
18 | }
19 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/base/MyGroup1.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.base;
2 |
3 | import com.intellij.icons.AllIcons;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.CommonDataKeys;
6 | import com.intellij.openapi.actionSystem.DefaultActionGroup;
7 | import com.intellij.openapi.editor.Editor;
8 |
9 | /**
10 | * Created by likunlun on 2020/7/11.
11 | */
12 | public class MyGroup1 extends DefaultActionGroup {
13 | @Override
14 | public void update(AnActionEvent e) {
15 | Editor editor = e.getData(CommonDataKeys.EDITOR);
16 | e.getPresentation().setVisible(true);
17 | e.getPresentation().setEnabled(editor != null);
18 | e.getPresentation().setIcon(AllIcons.General.Error);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultBuilder.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | final java.lang.StringBuilder sb = new java.lang.StringBuilder("$classname{");
3 | #set ($i = 0)
4 | #foreach ($member in $members)
5 | #if ($i == 0)
6 | sb.append("##
7 | #else
8 | sb.append(", ##
9 | #end
10 | #if ($member.string)
11 | $member.name='")##
12 | #else
13 | $member.name=")##
14 | #end
15 | #if ($member.primitiveArray || $member.objectArray)
16 | .append(java.util.Arrays.toString($member.name));
17 | #elseif ($member.string)
18 | .append($member.accessor).append('\'');
19 | #else
20 | .append($member.accessor);
21 | #end
22 | #set ($i = $i + 1)
23 | #end
24 | sb.append('}');
25 | return sb.toString();
26 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultConcatMemberGroovy.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | #if ( $members.size() > 0 )
3 | #set ( $i = 0 )
4 | return """\
5 | $classname{
6 | #foreach( $member in $members )
7 | #if ( $i > 0 ),
8 | #end
9 | #set($d = "$")
10 | #if ( $member.objectArray )
11 | $member.name=${d}{java.util.Arrays.toString($member.accessor)}##
12 | #elseif ( $member.primitiveArray)
13 | $member.name=${d}{java.util.Arrays.toString($member.accessor)}##
14 | #elseif ( $member.string )
15 | $member.name='$d$member.accessor'##
16 | #else
17 | $member.name=$d${member.accessor}##
18 | #end
19 | #set ( $i = $i + 1 )
20 | #end
21 |
22 | }"""
23 | #else
24 | return "$classname{}"
25 | #end
26 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | -Dfile.encoding=UTF-8
2 | # Copy this file as gradle.properties
3 | # It will be used for both compiling and running the plugin.
4 |
5 |
6 | # Path to a downloaded instance of Android Studio
7 | # This is used to add the android plugin dependencies to the project.
8 | # must point to the latest version of Android Studio.
9 | # You'll know it's right if you can find "$StudioCompilePath/lib/idea.jar"
10 | StudioCompilePath=/Applications/Android Studio.app/Contents/
11 | IntellijCompilePath=/Applications/IntelliJ IDEA CE.app/Contents/
12 |
13 |
14 | # Determines which IDE to run when using the "./gradlew runIdea" command.
15 | # This is useful to test the plugin on older versions of Android Studio or Intellij
16 | # Default value: $StudioCompilePath
17 | StudioRunPath=/Applications/Android Studio.app/Contents/
18 | IntellijRunPath=/Applications/IntelliJ IDEA CE.app/Contents/
--------------------------------------------------------------------------------
/ComparingReferencesInspection/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java'
3 | id 'org.jetbrains.intellij' version '0.4.21'
4 | }
5 |
6 | group 'com.lkl.plugin'
7 | version '1.0.0'
8 |
9 | sourceCompatibility = 1.8
10 |
11 | repositories {
12 | mavenCentral()
13 | }
14 |
15 | test {
16 | // Set idea.home.path to the absolute path to the intellij-community source
17 | // on your local machine.
18 | // systemProperty "idea.home.path", "/Users/jhake/Documents/source/comm"
19 | }
20 |
21 | dependencies {
22 | testCompile group: 'junit', name: 'junit', version: '4.12'
23 | }
24 |
25 | // See https://github.com/JetBrains/gradle-intellij-plugin/
26 | intellij {
27 | version = '2020.1'
28 | plugins = ['java']
29 | }
30 |
31 | buildSearchableOptions {
32 | enabled = false
33 | }
34 |
35 | patchPluginXml {
36 | version = project.version
37 | sinceBuild = '201'
38 | untilBuild = '201.*'
39 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'java'
3 | id 'org.jetbrains.intellij' version '0.4.21'
4 | }
5 |
6 | group 'com.lkl.plugin'
7 | version '1.0.0'
8 |
9 | repositories {
10 | mavenCentral()
11 | }
12 |
13 | dependencies {
14 | compileOnly fileTree(dir: "$IntellijCompilePath/plugins/java/lib", include: ['*.jar'])
15 | compileOnly fileTree(dir: "$IntellijCompilePath/lib", include: ['*.jar'])
16 |
17 | testCompile fileTree(dir: "$IntellijCompilePath/plugins/java/lib", include: ['*.jar'])
18 | testCompile fileTree(dir: "$IntellijCompilePath/lib", include: ['*.jar'])
19 | testCompile group: 'junit', name: 'junit', version: '4.12'
20 | }
21 |
22 | // See https://github.com/JetBrains/gradle-intellij-plugin/
23 | intellij {
24 | version '2019.3'
25 | plugins 'java'
26 | }
27 | patchPluginXml {
28 | changeNotes """
29 | Add change notes here.
30 | most HTML tags may be used"""
31 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultConcatMember.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | #if ( $members.size() > 0 )
3 | #set ( $i = 0 )
4 | return "$classname{" +
5 | #foreach( $member in $members )
6 | #if ( $i == 0 )
7 | "##
8 | #else
9 | ", ##
10 | #end
11 | #if ( $member.objectArray )
12 | #if ($java_version < 5)
13 | $member.name=" + ($member.accessor == null ? null : java.util.Arrays.asList($member.accessor)) +
14 | #else
15 | $member.name=" + java.util.Arrays.toString($member.accessor) +
16 | #end
17 | #elseif ( $member.primitiveArray && $java_version >= 5)
18 | $member.name=" + java.util.Arrays.toString($member.accessor) +
19 | #elseif ( $member.string )
20 | $member.name='" + $member.accessor + '\'' +
21 | #else
22 | $member.name=" + $member.accessor +
23 | #end
24 | #set ( $i = $i + 1 )
25 | #end
26 | '}';
27 | #else
28 | return "$classname{}";
29 | #end
30 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/GenerateToStringInterfaceFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2000-2014 JetBrains s.r.o.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring;
17 |
18 | import com.intellij.psi.PsiClass;
19 |
20 | /**
21 | * Nikolay.Tropin
22 | * 2014-12-01
23 | */
24 | public class GenerateToStringInterfaceFilter implements GenerateToStringClassFilter {
25 |
26 | @Override
27 | public boolean canGenerateToString(PsiClass psiClass) {
28 | return !psiClass.isInterface();
29 | }
30 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultBuffer.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | final java.lang.StringBuffer sb = new java.lang.StringBuffer("$classname{");
3 | #set ($i = 0)
4 | #foreach ($member in $members)
5 | #if ($i == 0)
6 | sb.append("##
7 | #else
8 | sb.append(", ##
9 | #end
10 | #if ($member.string)
11 | $member.name='")##
12 | #else
13 | $member.name=")##
14 | #end
15 | #if ($member.primitiveArray)
16 | ;
17 | if ($member.name == null) ##
18 | sb.append("null");
19 | else {
20 | sb.append('[');
21 | for (int i = 0; i < $member.name .length; ++i)
22 | sb.append(i == 0 ? "" : ", ").append($member.name [i]);
23 | sb.append(']');
24 | }
25 | #elseif ($member.objectArray)
26 | .append($member.name == null ? "null" : java.util.Arrays.asList($member.name).toString());
27 | #elseif ($member.string)
28 | .append($member.accessor).append('\'');
29 | #else
30 | .append($member.accessor);
31 | #end
32 | #set ($i = $i + 1)
33 | #end
34 | sb.append('}');
35 | return sb.toString();
36 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultConcatMemberSuperGroovy.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | #set($d = "$")
3 | #if ( $members.size() > 0 )
4 | #set ( $i = 0 )
5 | return """\
6 | $classname{
7 | #foreach( $member in $members )
8 | #if( $i > 0 ),
9 | #end
10 | #if ( $member.objectArray )
11 | $member.name=${d}{java.util.Arrays.toString($member.accessor)}##
12 | #elseif ( $member.primitiveArray)
13 | $member.name=${d}{java.util.Arrays.toString($member.accessor)}##
14 | #elseif ( $member.string )
15 | $member.name='$d$member.accessor'##
16 | #else
17 | $member.name=$d${member.accessor}##
18 | #end
19 | #set( $i = $i + 1 )
20 | #end
21 | #if( $class.hasSuper )
22 | #if( $i > 0 ),
23 | #end
24 | super=${d}{super.toString()}##
25 | #end
26 |
27 | }"""
28 | #else
29 | #if( $class.hasSuper )
30 | return "$classname{##
31 | super=${d}{super.toString()}##
32 | }"
33 | #else
34 | return "$classname{}"
35 | #end
36 | #end
37 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/base/InsertCharAction.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.base;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.editor.actionSystem.EditorActionManager;
6 | import com.intellij.openapi.editor.actionSystem.TypedAction;
7 | import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
8 |
9 | /**
10 | * Created by likunlun on 2020/7/11.
11 | */
12 | public class InsertCharAction extends AnAction {
13 | public InsertCharAction() {
14 | final EditorActionManager actionManager = EditorActionManager.getInstance();
15 | final TypedAction typedAction = actionManager.getTypedAction();
16 | MyTypedActionHandler handler = new MyTypedActionHandler();
17 | //将自定义的TypedActionHandler设置进去后,
18 | //返回旧的TypedActionHandler,即IDEA自身的TypedActionHandler
19 | TypedActionHandler oldHandler = typedAction.setupHandler(handler);
20 | handler.setOldHandler(oldHandler);
21 | }
22 |
23 | @Override
24 | public void actionPerformed(AnActionEvent e) {
25 |
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/GenerateToStringAction.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2007 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring;
17 |
18 | import com.intellij.codeInsight.generation.actions.BaseGenerateAction;
19 |
20 | /**
21 | * This action handles the generation of a {@code toString()} method that dumps the fields
22 | * of the class.
23 | */
24 | public class GenerateToStringAction extends BaseGenerateAction {
25 |
26 | public GenerateToStringAction() {
27 | super(new GenerateToStringActionHandlerImpl());
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/base/HelloWorldPlugin.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.base;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.PlatformDataKeys;
6 | import com.intellij.openapi.editor.Editor;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.openapi.ui.Messages;
9 | import org.jetbrains.annotations.Nls;
10 | import org.jetbrains.annotations.Nullable;
11 |
12 | /**
13 | * Created by likunlun on 2020/7/11.
14 | */
15 | public class HelloWorldPlugin extends AnAction {
16 | @Override
17 | public void update(AnActionEvent e) {
18 | Editor editor = e.getData(PlatformDataKeys.EDITOR);
19 |
20 | if (editor != null)
21 | e.getPresentation().setEnabled(true);
22 | else
23 | e.getPresentation().setEnabled(false);
24 |
25 | }
26 |
27 | @Override
28 | public void actionPerformed(AnActionEvent e) {
29 | // TODO: insert action logic here
30 | Project project = e.getData(PlatformDataKeys.PROJECT);
31 | Messages.showMessageDialog(project, "Hello World111!", "Information", Messages.getInformationIcon());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/util/EntryFactory.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.util;
2 |
3 | import com.intellij.psi.PsiClass;
4 | import com.intellij.psi.PsiField;
5 | import com.intellij.psi.PsiMethod;
6 | import org.jetbrains.java.generate.element.ElementFactory;
7 | import org.jetbrains.java.generate.element.FieldElement;
8 |
9 | public class EntryFactory {
10 | public static FieldEntry of(PsiField field, boolean useAccessor) {
11 | if (field == null) return null;
12 | return new FieldEntry(field, ElementFactory.newFieldElement(field, useAccessor));
13 | }
14 |
15 | public static FieldEntry of(PsiClass clazz, FieldElement element) {
16 | if (clazz == null || element == null) return null;
17 |
18 | PsiField field = clazz.findFieldByName(element.getName(), true);
19 | return new FieldEntry(field, element);
20 | }
21 |
22 | public static MethodEntry of(PsiMethod method) {
23 | if (method == null) return null;
24 | return new MethodEntry(method, ElementFactory.newMethodElement(method));
25 | }
26 |
27 | public static ClassEntry of(PsiClass clazz) {
28 | if (clazz == null) return null;
29 | return ClassEntry.of(clazz, ElementFactory.newClassElement(clazz));
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/DefaultConcatMemberSuper.vm:
--------------------------------------------------------------------------------
1 | public java.lang.String toString() {
2 | #if ( $members.size() > 0 )
3 | #set ( $i = 0 )
4 | return "$classname{" +
5 | #foreach( $member in $members )
6 | #if ( $i == 0 )
7 | "##
8 | #else
9 | ", ##
10 | #end
11 | #if ( $member.objectArray )
12 | #if ($java_version < 5)
13 | $member.name=" + ($member.accessor == null ? null : java.util.Arrays.asList($member.accessor)) +
14 | #else
15 | $member.name=" + java.util.Arrays.toString($member.accessor) +
16 | #end
17 | #elseif ( $member.primitiveArray && $java_version >= 5)
18 | $member.name=" + java.util.Arrays.toString($member.accessor) +
19 | #elseif ( $member.string )
20 | $member.name='" + $member.accessor + '\'' +
21 | #else
22 | $member.name=" + $member.accessor +
23 | #end
24 | #set ( $i = $i + 1 )
25 | #end
26 | #if ( $class.hasSuper )
27 | "} " + super.toString();
28 | #else
29 | '}';
30 | #end
31 | #else
32 | #if ( $class.hasSuper )
33 | return "$classname{} " + super.toString();
34 | #else
35 | return "$classname{}";
36 | #end
37 | #end
38 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/exception/TemplateResourceException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2007 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.exception;
17 |
18 | import org.jetbrains.java.generate.exception.PluginException;
19 |
20 | /**
21 | * Template resource related exceptions.
22 | *
23 | * Usually error loading or saving template resources.
24 | */
25 | public class TemplateResourceException extends PluginException {
26 |
27 | /**
28 | * Create template exception (error saving template, loading template etc.)
29 | *
30 | * @param msg message description.
31 | * @param cause the caused exception.
32 | */
33 | public TemplateResourceException(String msg, Throwable cause) {
34 | super(msg, cause);
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/base/MyGroup.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.base;
2 |
3 | import com.intellij.openapi.actionSystem.ActionGroup;
4 | import com.intellij.openapi.actionSystem.AnAction;
5 | import com.intellij.openapi.actionSystem.AnActionEvent;
6 | import com.intellij.openapi.actionSystem.PlatformDataKeys;
7 | import com.intellij.openapi.editor.CaretModel;
8 | import com.intellij.openapi.editor.Editor;
9 | import com.intellij.openapi.editor.SelectionModel;
10 | import org.jetbrains.annotations.NotNull;
11 | import org.jetbrains.annotations.Nullable;
12 |
13 | /**
14 | * Created by likunlun on 2020/7/11.
15 | */
16 | public class MyGroup extends ActionGroup {
17 | @NotNull
18 | @Override
19 | public AnAction[] getChildren(@Nullable AnActionEvent anActionEvent) {
20 | return new AnAction[]{new CustomAction("first"),new CustomAction("second")};
21 | }
22 |
23 | class CustomAction extends AnAction {
24 | public CustomAction(String text) {
25 | super(text);
26 | }
27 | @Override
28 | public void actionPerformed(@NotNull AnActionEvent e) {
29 | Editor editor = e.getData(PlatformDataKeys.EDITOR);
30 | if (editor == null)
31 | return;
32 |
33 | SelectionModel selectionModel = editor.getSelectionModel();
34 | CaretModel caretModel=editor.getCaretModel();
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/TemplatesState.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package com.lkl.plugin.tostring.template;
3 |
4 | import com.intellij.openapi.util.Comparing;
5 | import com.intellij.openapi.util.text.StringUtil;
6 | import com.intellij.util.xmlb.annotations.Attribute;
7 | import com.intellij.util.xmlb.annotations.OptionTag;
8 |
9 | import java.util.ArrayList;
10 | import java.util.List;
11 | import java.util.Objects;
12 |
13 | final class TemplatesState {
14 | @SuppressWarnings("SpellCheckingInspection")
15 | @OptionTag("defaultTempalteName")
16 | String oldDefaultTemplateName;
17 |
18 | @Attribute
19 | String defaultTemplateName = "";
20 |
21 | public final List templates = new ArrayList<>();
22 |
23 | @Override
24 | public boolean equals(Object o) {
25 | if (this == o) return true;
26 | if (o == null || getClass() != o.getClass()) return false;
27 | TemplatesState state = (TemplatesState)o;
28 | return Comparing.strEqual(defaultTemplateName, state.defaultTemplateName) &&
29 | Objects.equals(templates, state.templates);
30 | }
31 |
32 | @Override
33 | public int hashCode() {
34 | return Objects.hash(StringUtil.nullize(defaultTemplateName), templates);
35 | }
36 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/GenerateToStringClassFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2000-2014 JetBrains s.r.o.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring;
17 |
18 | import com.intellij.openapi.extensions.ExtensionPointName;
19 | import com.intellij.psi.PsiClass;
20 | import org.jetbrains.annotations.Contract;
21 |
22 | /**
23 | * An extension which allows to prohibit toString generation for some classes
24 | */
25 | public interface GenerateToStringClassFilter {
26 | ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.generation.toStringClassFilter");
27 |
28 | /**
29 | * @param psiClass class to check
30 | * @return return false if toString should not be generated for the class
31 | */
32 | @Contract(pure = true)
33 | boolean canGenerateToString(PsiClass psiClass);
34 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/ui/ClassSelectionPane.form:
--------------------------------------------------------------------------------
1 |
2 |
35 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/base/MyTypedActionHandler.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.base;
2 |
3 | import com.intellij.openapi.actionSystem.DataContext;
4 | import com.intellij.openapi.editor.CaretModel;
5 | import com.intellij.openapi.editor.Document;
6 | import com.intellij.openapi.editor.Editor;
7 | import com.intellij.openapi.editor.actionSystem.TypedActionHandler;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | /**
11 | * Created by likunlun on 2020/7/11.
12 | */
13 | public class MyTypedActionHandler implements TypedActionHandler {
14 | private TypedActionHandler oldHandler;
15 | private boolean isBegin = true;
16 | private int caretLine = 0;
17 |
18 | @Override
19 | public void execute(@NotNull Editor editor, char c, @NotNull DataContext dataContext) {
20 | if (oldHandler != null)
21 | oldHandler.execute(editor, c, dataContext);
22 |
23 | Document document = editor.getDocument();
24 | CaretModel caretModel = editor.getCaretModel();
25 | int caretOffset = caretModel.getOffset();
26 | int line = document.getLineNumber(caretOffset);
27 | if (isBegin) {
28 | document.insertString(document.getLineStartOffset(line), String.valueOf(c) + "\n");
29 | caretLine = line + 1;
30 | isBegin = false;
31 | } else {
32 | if (line != caretLine) {
33 | isBegin = true;
34 | execute(editor, c, dataContext);
35 | } else {
36 | document.insertString(document.getLineEndOffset(line - 1), String.valueOf(c));
37 | }
38 | }
39 | System.out.println(caretLine + "," + line);
40 |
41 | }
42 |
43 | public void setOldHandler(TypedActionHandler oldHandler) {
44 | this.oldHandler = oldHandler;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/config/ClassSelectionConfig.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.config;
2 |
3 | import javax.xml.bind.annotation.XmlAccessType;
4 | import javax.xml.bind.annotation.XmlAccessorType;
5 | import javax.xml.bind.annotation.XmlRootElement;
6 |
7 | @XmlRootElement(name = "classSelection")
8 | @XmlAccessorType(XmlAccessType.FIELD)
9 | public class ClassSelectionConfig implements PipelineStep {
10 | public String initialClass = "$class0.qualifiedName";
11 | public boolean enabled = true;
12 | public String postfix = "";
13 | @Override public String type() {
14 | return "class-selection";
15 | }
16 |
17 | @Override
18 | public String postfix() {
19 | return postfix;
20 | }
21 |
22 | @Override
23 | public void postfix(String postfix) {
24 | this.postfix = postfix;
25 | }
26 |
27 | @Override
28 | public boolean enabled() {
29 | return enabled;
30 | }
31 |
32 | @Override
33 | public void enabled(boolean enabled) {
34 | this.enabled = enabled;
35 | }
36 |
37 | @Override
38 | public boolean equals(Object o) {
39 | if (this == o) return true;
40 | if (o == null || getClass() != o.getClass()) return false;
41 |
42 | ClassSelectionConfig that = (ClassSelectionConfig) o;
43 |
44 | if (enabled != that.enabled) return false;
45 | if (initialClass != null ? !initialClass.equals(that.initialClass) : that.initialClass != null) return false;
46 | return postfix != null ? postfix.equals(that.postfix) : that.postfix == null;
47 | }
48 |
49 | @Override
50 | public int hashCode() {
51 | int result = initialClass != null ? initialClass.hashCode() : 0;
52 | result = 31 * result + (enabled ? 1 : 0);
53 | result = 31 * result + (postfix != null ? postfix.hashCode() : 0);
54 | return result;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/PsiAugmentProvider/CustomPsiAugmentProvider.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.PsiAugmentProvider;
2 |
3 | import com.intellij.lang.java.JavaLanguage;
4 | import com.intellij.psi.PsiElement;
5 | import com.intellij.psi.PsiManager;
6 | import com.intellij.psi.PsiModifier;
7 | import com.intellij.psi.PsiType;
8 | import com.intellij.psi.augment.PsiAugmentProvider;
9 | import com.intellij.psi.impl.light.LightFieldBuilder;
10 | import com.intellij.psi.impl.light.LightMethodBuilder;
11 | import com.intellij.psi.impl.light.LightModifierList;
12 | import org.jetbrains.annotations.NotNull;
13 |
14 | import java.util.List;
15 |
16 | public class CustomPsiAugmentProvider extends PsiAugmentProvider {
17 | @NotNull
18 | @Override
19 | protected List getAugments(@NotNull PsiElement element, @NotNull Class type) {
20 |
21 | // PsiManager manager = psiField.getAugmentsManager();
22 | // LightMethodBuilder method = new LightMethodBuilder(manager, JavaLanguage.INSTANCE, methodName);
23 | // method.addModifier(PsiModifier.PUBLIC);
24 | // method.setContainingClass(psiClass);
25 | // method.setNavigationElement(psiField);
26 | // method.addParameter(psiField.getName(), psiField.getType());
27 | // method.setMethodReturnType(PsiType.VOID);
28 | //
29 | // PsiType psiLoggerType = psiElementFactory.createTypeFromText(LOGGER_TYPE, psiClass);
30 | // LightFieldBuilder loggerField = new LightFieldBuilder(manager, LOGGER_NAME, psiLoggerType);
31 | // LightModifierList modifierList = (LightModifierList) loggerField.getModifierList();
32 | // modifierList.addModifier(PsiModifier.PRIVATE);
33 | // modifierList.addModifier(PsiModifier.STATIC);
34 | // modifierList.addModifier(PsiModifier.FINAL);
35 | // loggerField.setContainingClass(psiClass);
36 | // loggerField.setNavigationElement(psiAnnotation);
37 |
38 | return super.getAugments(element, type);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/config/CodeTemplateList.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.config;
2 |
3 | import javax.xml.bind.JAXB;
4 | import javax.xml.bind.annotation.XmlAccessType;
5 | import javax.xml.bind.annotation.XmlAccessorType;
6 | import javax.xml.bind.annotation.XmlElement;
7 | import javax.xml.bind.annotation.XmlElementWrapper;
8 | import java.io.StringReader;
9 | import java.io.StringWriter;
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | @XmlAccessorType(XmlAccessType.FIELD)
14 | public class CodeTemplateList {
15 | @XmlElement(type = CodeTemplate.class)
16 | @XmlElementWrapper
17 | private List templates = new ArrayList<>();
18 |
19 | public CodeTemplateList() {}
20 | public CodeTemplateList(List templates) {
21 | this.templates.addAll(templates);
22 | }
23 | public CodeTemplateList(CodeTemplate template) {
24 | this.templates.add(template);
25 | }
26 |
27 | public List getTemplates() {
28 | templates.forEach(CodeTemplate::regenerateId);
29 | return templates;
30 | }
31 |
32 | public void setTemplates(List templates) {
33 | this.templates = templates;
34 | }
35 |
36 | public static List fromXML(String xml) {
37 | CodeTemplateList list = JAXB.unmarshal(new StringReader(xml), CodeTemplateList.class);
38 | return list.getTemplates();
39 | }
40 |
41 | public static String toXML(List templates) {
42 | CodeTemplateList templateList = new CodeTemplateList(templates);
43 | StringWriter sw = new StringWriter();
44 | JAXB.marshal(templateList, sw);
45 | return sw.toString();
46 | }
47 | public static String toXML(CodeTemplate templates) {
48 | CodeTemplateList templateList = new CodeTemplateList(templates);
49 | StringWriter sw = new StringWriter();
50 | JAXB.marshal(templateList, sw);
51 | return sw.toString();
52 | }
53 | }
54 |
55 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/config/DuplicatePolicy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.config;
17 |
18 | import com.intellij.openapi.editor.Editor;
19 | import com.intellij.psi.PsiClass;
20 | import com.intellij.psi.PsiMethod;
21 | import org.jetbrains.annotations.NotNull;
22 | import org.jetbrains.java.generate.config.ConflictResolutionPolicy;
23 | import org.jetbrains.java.generate.config.InsertNewMethodStrategy;
24 |
25 | /**
26 | * This policy is to create a duplicate {@code toString} method.
27 | */
28 | public final class DuplicatePolicy implements ConflictResolutionPolicy {
29 |
30 | private static final DuplicatePolicy instance = new DuplicatePolicy();
31 | private InsertNewMethodStrategy newMethodStrategy = InsertAtCaretStrategy.getInstance();
32 |
33 | private DuplicatePolicy() {}
34 |
35 | public static DuplicatePolicy getInstance() {
36 | return instance;
37 | }
38 |
39 | @Override
40 | public void setNewMethodStrategy(InsertNewMethodStrategy strategy) {
41 | newMethodStrategy = strategy;
42 | }
43 |
44 | @Override
45 | public PsiMethod applyMethod(PsiClass clazz, PsiMethod existingMethod, @NotNull PsiMethod newMethod, Editor editor) {
46 | return newMethodStrategy.insertNewMethod(clazz, newMethod, editor);
47 | }
48 |
49 | public String toString() {
50 | return "Duplicate";
51 | }
52 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/configurable/SingleFileExecutionConfigurable.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.configurable;
2 |
3 | import com.intellij.openapi.options.ConfigurationException;
4 | import com.intellij.openapi.options.SearchableConfigurable;
5 | import com.intellij.openapi.project.Project;
6 | import org.jetbrains.annotations.Nls;
7 | import org.jetbrains.annotations.NotNull;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 | import javax.swing.*;
11 |
12 | public class SingleFileExecutionConfigurable implements SearchableConfigurable {
13 | private SingleFileExecutionConfigurableGUI mGUI;
14 | private final SingleFileExecutionConfig mConfig;
15 |
16 | @SuppressWarnings("FieldCanBeLocal")
17 | private final Project mProject;
18 |
19 | public SingleFileExecutionConfigurable(@NotNull Project project) {
20 | mProject = project;
21 | mConfig = SingleFileExecutionConfig.getInstance(project);
22 | }
23 |
24 | @Nls
25 | @Override
26 | public String getDisplayName() {
27 | return "Single File Execution Plugin";
28 | }
29 |
30 | @Nullable
31 | @Override
32 | public String getHelpTopic() {
33 | return "preference.SingleFileExecutionConfigurable";
34 | }
35 |
36 | @NotNull
37 | @Override
38 | public String getId() {
39 | return "preference.SingleFileExecutionConfigurable";
40 | }
41 |
42 | @Nullable
43 | @Override
44 | public Runnable enableSearch(String s) {
45 | return null;
46 | }
47 |
48 | @Nullable
49 | @Override
50 | public JComponent createComponent() {
51 | mGUI = new SingleFileExecutionConfigurableGUI();
52 | mGUI.createUI(mProject);
53 | return mGUI.getRootPanel();
54 | }
55 |
56 | @Override
57 | public boolean isModified() {
58 | return mGUI.isModified();
59 | }
60 |
61 | @Override
62 | public void apply() throws ConfigurationException {
63 | mGUI.apply();
64 | }
65 |
66 | @Override
67 | public void reset() {
68 | mGUI.reset();
69 | }
70 |
71 | @Override
72 | public void disposeUIResources() {
73 | mGUI = null;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/config/InsertAtCaretStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.config;
17 |
18 | import com.intellij.codeInsight.generation.GenerateMembersUtil;
19 | import com.intellij.codeInsight.generation.PsiGenerationInfo;
20 | import com.intellij.openapi.editor.Editor;
21 | import com.intellij.psi.PsiClass;
22 | import com.intellij.psi.PsiMethod;
23 | import org.jetbrains.annotations.NotNull;
24 | import org.jetbrains.java.generate.config.InsertNewMethodStrategy;
25 |
26 | import java.util.Collections;
27 |
28 | /**
29 | * Inserts the method at the caret position.
30 | */
31 | public final class InsertAtCaretStrategy implements InsertNewMethodStrategy {
32 |
33 | private static final InsertAtCaretStrategy instance = new InsertAtCaretStrategy();
34 |
35 | private InsertAtCaretStrategy() {}
36 |
37 | public static InsertAtCaretStrategy getInstance() {
38 | return instance;
39 | }
40 |
41 | @Override
42 | public PsiMethod insertNewMethod(PsiClass clazz, @NotNull PsiMethod newMethod, Editor editor) {
43 | int offset = (editor != null) ? editor.getCaretModel().getOffset() : (clazz.getTextRange().getEndOffset() - 1);
44 | final PsiGenerationInfo generationInfo = new PsiGenerationInfo<>(newMethod, false);
45 | GenerateMembersUtil.insertMembersAtOffset(clazz, offset, Collections.singletonList(generationInfo));
46 | return generationInfo.getPsiMember();
47 | }
48 |
49 | public String toString() {
50 | return "At caret";
51 | }
52 | }
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/kotlin/com/lkl/plugin/Cons.kt:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin
2 |
3 | /**
4 | * Created by XQ Yang on 2018/6/26 11:14.
5 | * Description : 常量
6 | */
7 |
8 | fun getContractName(name: String) = "I${name}Contract"
9 |
10 | fun getViewInfName(name: String) = "I${name}View"
11 | fun getPresenterInfName(name: String) = "I${name}Presenter"
12 | fun getModelInfName(name: String) = "I${name}Model"
13 |
14 | const val USE_PROJECT_CONFIG = "use_project_config"
15 | const val GENERATE_MODEL_CONFIG = "generate_model_config"
16 | const val GOTO_SETTING = "Please go to File-> Settings -> OtherSettings -> MvpAutoCodePlus set."
17 | const val IS_NOT_SET = "Is not set"
18 | const val NO_SUPER_CLASS = "The implementation class will have no superclass"
19 |
20 | const val CONTRACT = "contract"
21 | const val VIEW = "view"
22 | const val PRESENTER = "presenter"
23 | const val MODEL = "model"
24 |
25 |
26 | const val SUPER_VIEW = "super_view"
27 | const val SUPER_PRESENTER = "super_presenter"
28 | const val SUPER_MODEL = "super_model"
29 | const val SUPER_VIEW_ACTIVITY = "super_view_activity"
30 | const val SUPER_VIEW_FRAGMENT = "super_view_fragment"
31 | const val SUPER_PRESENTER_IMPL = "super_presenter_impl"
32 | const val SUPER_MODEL_IMPL = "super_model_impl"
33 | const val COMMENT_AUTHOR = "comment_author"
34 |
35 |
36 | const val CONTRACT_TP_NAME_JAVA = "JavaMvpAutoCodePlusContract"
37 | const val CONTRACT_TP_NAME_KOTLIN = "KotlinMvpAutoCodePlusContract"
38 | const val CONTRACT_TP_NO_MODEL_NAME_JAVA = "JavaMvpAutoCodePlusContractNoModel"
39 | const val CONTRACT_TP_NO_MODEL_NAME_KOTLIN = "KotlinMvpAutoCodePlusContractNoModel"
40 | const val VIEW_IMPL_TP_ACTIVITY_JAVA = "JavaMvpAutoCodePlusViewActivityImpl"
41 | const val VIEW_IMPL_TP_ACTIVITY_KOTLIN = "KotlinMvpAutoCodePlusViewActivityImpl"
42 | const val VIEW_IMPL_TP_FRAGMENT_JAVA = "JavaMvpAutoCodePlusViewFragmentImpl"
43 | const val VIEW_IMPL_TP_FRAGMENT_KOTLIN = "KotlinMvpAutoCodePlusViewFragmentImpl"
44 | const val PRESENTER_IMPL_TP_JAVA = "JavaMvpAutoCodePlusPresenterImpl"
45 | const val PRESENTER_IMPL_TP_KOTLIN = "KotlinMvpAutoCodePlusPresenterImpl"
46 | const val MODEL_IMPL_TP_JAVA = "JavaMvpAutoCodePlusModelImpl"
47 | const val MODEL_IMPL_TP_KOTLIN = "KotlinMvpAutoCodePlusModelImpl"
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/config/ReplacePolicy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2007 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.config;
17 |
18 | import com.intellij.openapi.editor.Editor;
19 | import com.intellij.psi.PsiClass;
20 | import com.intellij.psi.PsiMethod;
21 | import com.intellij.util.IncorrectOperationException;
22 | import org.jetbrains.annotations.NotNull;
23 | import org.jetbrains.java.generate.config.ConflictResolutionPolicy;
24 | import org.jetbrains.java.generate.config.InsertNewMethodStrategy;
25 |
26 | /**
27 | * This policy is to replace the existing {@code toString} method.
28 | */
29 | public final class ReplacePolicy implements ConflictResolutionPolicy {
30 |
31 | private static final ReplacePolicy instance = new ReplacePolicy();
32 |
33 | private ReplacePolicy() {
34 | }
35 |
36 | public static ReplacePolicy getInstance() {
37 | return instance;
38 | }
39 |
40 | @Override
41 | public void setNewMethodStrategy(InsertNewMethodStrategy strategy) {
42 | DuplicatePolicy.getInstance().setNewMethodStrategy(strategy);
43 | }
44 |
45 | @Override
46 | public PsiMethod applyMethod(PsiClass clazz, PsiMethod existingMethod, @NotNull PsiMethod newMethod, Editor editor) throws IncorrectOperationException {
47 | PsiMethod generatedMethod = DuplicatePolicy.getInstance().applyMethod(clazz, null, newMethod, editor);
48 | if (existingMethod != null) {
49 | existingMethod.delete();
50 | }
51 | return generatedMethod;
52 | }
53 |
54 | public String toString() {
55 | return "Replace existing";
56 | }
57 |
58 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/element/ElementComparator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2007 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.element;
17 |
18 | import java.util.Comparator;
19 |
20 | /**
21 | * Comparator to sort elements by it's name.
22 | */
23 | public class ElementComparator implements Comparator {
24 |
25 | private final int sort;
26 |
27 | /**
28 | * Construts a comparator that sorts by element name.
29 | *
30 | * @param sort the sorting order (0 = none, 1 = asc, 2 = desc)
31 | */
32 | public ElementComparator(int sort) {
33 | this.sort = sort;
34 | }
35 |
36 | @Override
37 | public int compare(Element e1, Element e2) {
38 | if (sort == 0) {
39 | return 0;
40 | }
41 |
42 | String name1 = getElementNameNoLeadingUnderscore(e1);
43 | String name2 = getElementNameNoLeadingUnderscore(e2);
44 |
45 | int res = name1.compareToIgnoreCase(name2);
46 | if (sort == 2) {
47 | res = -1 * res; // flip result if desc
48 | }
49 |
50 | return res;
51 | }
52 |
53 | /**
54 | * Get's the element name without any leading underscores.
55 | *
56 | * Examples: "_age" => "age", "birthday" => "birthday", "year_" => "year_"
57 | *
58 | * @param e the element
59 | * @return the name without _ in the start of the name.
60 | */
61 | private static String getElementNameNoLeadingUnderscore(Element e) {
62 | String name = e.getName();
63 | if (name.startsWith("_")) {
64 | return name.substring(1);
65 | } else {
66 | return name;
67 | }
68 | }
69 |
70 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/worker/JavaCaretWorker.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.worker;
2 |
3 | import com.intellij.openapi.command.WriteCommandAction;
4 | import com.intellij.openapi.diagnostic.Logger;
5 | import com.intellij.openapi.editor.Document;
6 | import com.intellij.openapi.editor.Editor;
7 | import com.intellij.openapi.editor.SelectionModel;
8 | import com.intellij.openapi.project.Project;
9 | import com.intellij.psi.PsiClass;
10 | import com.intellij.psi.PsiDocumentManager;
11 | import com.intellij.psi.PsiElement;
12 | import com.intellij.psi.PsiJavaFile;
13 | import com.intellij.psi.codeStyle.JavaCodeStyleManager;
14 | import com.intellij.psi.util.PsiTreeUtil;
15 | import com.lkl.plugin.codegenerator.config.CodeTemplate;
16 | import com.lkl.plugin.codegenerator.util.GenerationUtil;
17 | import org.jetbrains.annotations.NotNull;
18 |
19 | import java.util.Map;
20 |
21 | public class JavaCaretWorker {
22 | private static final Logger logger = Logger.getInstance(JavaCaretWorker.class);
23 |
24 | public static void execute(@NotNull CodeTemplate codeTemplate, @NotNull PsiJavaFile file, @NotNull Editor editor, @NotNull Map context) {
25 | final Project project = file.getProject();
26 | String content = GenerationUtil.velocityEvaluate(project, context, null, codeTemplate.template);
27 | if (logger.isDebugEnabled())
28 | logger.debug("Method body generated from Velocity:\n" + content);
29 |
30 | //Access document, caret, and selection
31 | final Document document = editor.getDocument();
32 | final SelectionModel selectionModel = editor.getSelectionModel();
33 |
34 | final int start = selectionModel.getSelectionStart();
35 | final int end = selectionModel.getSelectionEnd();
36 | WriteCommandAction.runWriteCommandAction(project, () -> {
37 | document.replaceString(start, end, content);
38 | PsiDocumentManager.getInstance(project).commitDocument(document);
39 | PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
40 | PsiClass clazz = PsiTreeUtil.getParentOfType(element, PsiClass.class, false);
41 | JavaCodeStyleManager.getInstance(project).shortenClassReferences(clazz.getContainingFile());
42 | });
43 | selectionModel.removeSelection();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/kotlin/com/lkl/plugin/maker/ComponentRegister.kt:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.maker
2 |
3 | import com.intellij.openapi.command.WriteCommandAction
4 | import com.intellij.openapi.project.Project
5 | import com.intellij.openapi.vfs.ReadonlyStatusHandler
6 | import com.intellij.psi.PsiClass
7 | import com.intellij.psi.PsiPackage
8 | import org.jetbrains.android.dom.manifest.Application
9 | import org.jetbrains.android.dom.manifest.ApplicationComponent
10 | import org.jetbrains.android.dom.manifest.Manifest
11 | import org.jetbrains.android.dom.resources.ResourceValue
12 | import org.jetbrains.android.facet.AndroidFacet
13 | import org.jetbrains.android.facet.AndroidRootUtil
14 | import org.jetbrains.android.util.AndroidUtils
15 |
16 | /**
17 | * @describe
18 | * @author longforus
19 | * @date 2020/3/18 15:11
20 | */
21 | object ComponentRegister {
22 |
23 | fun registerActivity(project: Project, aClass: PsiClass?, aPackage: PsiPackage?, facet: AndroidFacet, label: String?) {
24 | val manifestFile = AndroidRootUtil.getPrimaryManifestFile(facet)
25 | if (manifestFile != null && ReadonlyStatusHandler.ensureFilesWritable(facet.module.project, manifestFile)) {
26 | val manifest = AndroidUtils.loadDomElement(facet.module, manifestFile,
27 | Manifest::class.java)
28 | if (manifest != null) {
29 | val packageName = manifest.getPackage().value
30 | if (packageName == null || packageName.isEmpty()) {
31 | manifest.getPackage().value = aPackage?.qualifiedName
32 | }
33 | val application = manifest.application
34 | if (application != null) {
35 | WriteCommandAction.writeCommandAction(project, aClass!!.containingFile).run {
36 | val component = addToManifest(aClass, application)
37 | if (component != null && !label.isNullOrEmpty()) {
38 | component.label.value = ResourceValue.literal(label)
39 | }
40 | }
41 |
42 | }
43 | }
44 | }
45 | }
46 |
47 |
48 | fun addToManifest(aClass: PsiClass, application: Application): ApplicationComponent? {
49 | val activity = application.addActivity()
50 | activity.activityClass.value = aClass
51 | return activity
52 | }
53 |
54 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # IntellijPluginStudy
2 | Intellij plugin开发研究
3 |
4 | open第三方开源plugin项目时,需要在项目根目录下的*.iml文件修改一下module type为``
5 |
6 | ## Intellij plugin基础
7 |
8 | * [编写你的第一个plugin Hello World](./docs/base/helloWorld.md)
9 | * [Building Plugins with Gradle](./docs/base/gradlePlugin.md)
10 | * [Kotlin for Plugin Developers](./docs/base/kotlinPlugin.md)
11 | * [Action机制](./docs/base/action.md)
12 | * [插件开发之Editor](./docs/base/editor.md)
13 | * [打印日志,查看日志](./docs/base/log.md)
14 |
15 | ## Program Structure Interface (PSI)
16 |
17 | 程序结构接口(通常称为PSI)是IntelliJ平台中的一层,负责解析文件并创建语法和语义代码模型,以支持该平台的许多功能。
18 |
19 | * [介绍](./docs/psi/introduction.md)
20 | * [PSI使用](./docs/psi/use.md)
21 | * [PsiAugmentProvider](./docs/psi/psiAugmentProvider.md)
22 | * [StructureViewExtension](./docs/psi/structureViewExtension.md)
23 |
24 | ## Intellij plugin进阶
25 |
26 | * [IntelliJ Plugin Development introduction: PersistStateComponent](./docs/advanced/persistStateComponent.md)
27 | * [IntelliJ Plugin Development introduction: ApplicationConfigurable, ProjectConfigurable](./docs/advanced/applicationConfigurable.md)
28 | * [generate-tostring](./docs/advanced/generateTostring.md)
29 | * [代码检查 Code Inspections](./docs/advanced/codeInspections.md)
30 |
31 | ## 参考文献
32 |
33 | [[Intellij Idea 插件 番外] Api讲解(类、方法等)](https://blog.csdn.net/guohaiyang1992/article/details/79019094)
34 |
35 | [AndroidStudio插件开发(进阶篇之Action机制)](https://blog.csdn.net/huachao1001/article/details/53883500)
36 |
37 | [IntelliJ IDEA插件开发](https://blog.csdn.net/O4dC8OjO7ZL6/article/details/79722289)
38 |
39 | [AS插件开发:根据特定格式的文本自动生成Java Bean文件或字段](https://blog.csdn.net/qq_27258799/article/details/79295251)
40 |
41 | [https://www.cnblogs.com/liqiking/p/6792991.html](https://www.cnblogs.com/liqiking/p/6792991.html)
42 |
43 | [震惊!!!编码速度提高10倍的秘诀是....](https://blog.csdn.net/y4x5M0nivSrJaY3X92c/article/details/106131947)
44 |
45 | [https://github.com/longforus/MvpAutoCodePlus](https://github.com/longforus/MvpAutoCodePlus)
46 |
47 | [lombok-intellij-plugin](https://github.com/mplushnikov/lombok-intellij-plugin)
48 |
49 | [IntelliJ Platform SDK](https://www.jetbrains.org/intellij/sdk/docs/intro/welcome.html)
50 |
51 | [https://www.jetbrains.com/help/idea/getting-started.html](https://www.jetbrains.com/help/idea/getting-started.html)
52 |
53 | [https://www.jetbrains.org/intellij/sdk/docs/tutorials/editor_basics.html](https://www.jetbrains.org/intellij/sdk/docs/tutorials/editor_basics.html)
54 |
55 | [http://velocity.apache.org/](http://velocity.apache.org/)
56 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/StructureViewExtension/CustomStructureViewExtension.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.StructureViewExtension;
2 |
3 | import com.intellij.ide.structureView.StructureViewExtension;
4 | import com.intellij.ide.structureView.StructureViewTreeElement;
5 | import com.intellij.ide.structureView.impl.java.JavaClassTreeElement;
6 | import com.intellij.ide.structureView.impl.java.PsiFieldTreeElement;
7 | import com.intellij.ide.structureView.impl.java.PsiMethodTreeElement;
8 | import com.intellij.openapi.editor.Editor;
9 | import com.intellij.psi.PsiClass;
10 | import com.intellij.psi.PsiElement;
11 | import com.intellij.psi.PsiField;
12 | import com.intellij.psi.PsiMethod;
13 | import org.jetbrains.annotations.Nullable;
14 |
15 | import java.util.ArrayList;
16 | import java.util.Collection;
17 |
18 | public class CustomStructureViewExtension implements StructureViewExtension {
19 | @Override
20 | public Class extends PsiElement> getType() {
21 | return null;
22 | }
23 |
24 | @Nullable
25 | @Override
26 | public Object getCurrentEditorElement(Editor editor, PsiElement psiElement) {
27 | return null;
28 | }
29 |
30 | @Override
31 | public StructureViewTreeElement[] getChildren(PsiElement parent) {
32 | Collection result = new ArrayList();
33 | final PsiClass psiClass = (PsiClass) parent;
34 |
35 | // for (PsiField psiField : psiClass.getFields()) {
36 | // if (psiField instanceof LombokLightFieldBuilder) {
37 | // result.add(new PsiFieldTreeElement(psiField, false));
38 | // }
39 | // }
40 | //
41 | // for (PsiMethod psiMethod : psiClass.getMethods()) {
42 | // if (psiMethod instanceof LombokLightMethodBuilder) {
43 | // result.add(new PsiMethodTreeElement(psiMethod, false));
44 | // }
45 | // }
46 | //
47 | // for (PsiClass psiInnerClass : psiClass.getInnerClasses()) {
48 | // if (psiInnerClass instanceof LombokLightClassBuilder) {
49 | // result.add(new JavaClassTreeElement(psiInnerClass, false, new HashSet() {{
50 | // add(psiClass);
51 | // }}));
52 | // }
53 | // }
54 |
55 | if (!result.isEmpty()) {
56 | return result.toArray(new StructureViewTreeElement[result.size()]);
57 | } else {
58 | return StructureViewTreeElement.EMPTY_ARRAY;
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/docs/psi/structureViewExtension.md:
--------------------------------------------------------------------------------
1 | # StructureViewExtension
2 |
3 | 顾名思义,IDEA提供的这个扩展接口就是为了对其提供的Structure功能进行扩展,同样以lombok项目为例,Structcture中能够清晰明了的显示当前类的结构,如下图所示:
4 |
5 | 
6 |
7 | `Structcture`中详细显示当前类中的字段和方法,如果我们通过PsiAugmentProvider提供了相关的字段和方法,如果没有继承`StructureViewExtension`并重写其相关的方法,那么在如图所示的structure结构中就不会显示相关的字段和方法。所以一般使用了`PsiAugmentProvider`都需要再继承`StructureViewExtension`并重写相应的方法。
8 |
9 | `StructureViewExtension`接口中字段和方法如下:
10 | ```java
11 | ExtensionPointName EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.lang.structureViewExtension");
12 |
13 | Class extends PsiElement> getType();
14 |
15 | StructureViewTreeElement[] getChildren(PsiElement parent);
16 |
17 | @Nullable
18 | Object getCurrentEditorElement(Editor editor, PsiElement parent);
19 | ```
20 | * **EXTENSION_POINT_NAME**字段是创建一个扩展点,用于在plugin.xml中配置使用
21 | * **getType()**:获得具体的类型,一般为PsiClass.class
22 | * **getCurrentEditorElement()**:由于只查看相应的结构,不需要获得编辑对象,返回nulll即可
23 | * **getChildren()**:获得子元素,还记得在PsiAugmentProvider中我们通过LightFieldBuilder或者LightMethodBuilder来创建字段或者对象么;如果需要扩展StructureViewExtension,这里可以继承LightFieldBuilder或者LightMethodBuilder来创建相应的方法,getChildren()中遍历字段和方法,通过instanceof判断是否是为具体的对象,如果是则加入到result列表中即可
24 |
25 | ```java
26 | @Override
27 | public StructureViewTreeElement[] getChildren(PsiElement parent) {
28 | Collection result = new ArrayList();
29 | final PsiClass psiClass = (PsiClass) parent;
30 |
31 | for (PsiField psiField : psiClass.getFields()) {
32 | if (psiField instanceof LombokLightFieldBuilder) {
33 | result.add(new PsiFieldTreeElement(psiField, false));
34 | }
35 | }
36 |
37 | for (PsiMethod psiMethod : psiClass.getMethods()) {
38 | if (psiMethod instanceof LombokLightMethodBuilder) {
39 | result.add(new PsiMethodTreeElement(psiMethod, false));
40 | }
41 | }
42 |
43 | for (PsiClass psiInnerClass : psiClass.getInnerClasses()) {
44 | if (psiInnerClass instanceof LombokLightClassBuilder) {
45 | result.add(new JavaClassTreeElement(psiInnerClass, false, new HashSet() {{
46 | add(psiClass);
47 | }}));
48 | }
49 | }
50 |
51 | if (!result.isEmpty()) {
52 | return result.toArray(new StructureViewTreeElement[result.size()]);
53 | } else {
54 | return StructureViewTreeElement.EMPTY_ARRAY;
55 | }
56 | }
57 | ```
58 |
59 | ## 参考文献
60 |
61 | [IntelliJ IDEA插件开发指南(二)](https://blog.csdn.net/ExcellentYuXiao/article/details/80273347)
62 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/view/MethodExistsDialog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2007 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.view;
17 |
18 | import com.intellij.java.JavaBundle;
19 | import com.intellij.openapi.ui.Messages;
20 | import org.jetbrains.java.generate.config.CancelPolicy;
21 | import org.jetbrains.java.generate.config.ConflictResolutionPolicy;
22 | import org.jetbrains.java.generate.config.DuplicatePolicy;
23 | import org.jetbrains.java.generate.config.ReplacePolicy;
24 |
25 | /**
26 | * This is a dialog when the {@code toString()} method already exists.
27 | *
28 | * The user now has the choices to either:
29 | *
30 | * Replace existing method
31 | * Create a duplicate method
32 | * Cancel
33 | *
34 | */
35 | public final class MethodExistsDialog {
36 | private MethodExistsDialog() {
37 | }
38 |
39 | /**
40 | * Shows this dialog.
41 | *
42 | * The user now has the choices to either:
43 | *
44 | * Replace existing method
45 | * Create a duplicate method
46 | * Cancel
47 | *
48 | *
49 | * @param targetMethodName the name of the target method (toString)
50 | * @return the chosen conflict resolution policy (never null)
51 | */
52 | public static ConflictResolutionPolicy showDialog(String targetMethodName) {
53 | int exit = Messages.showYesNoCancelDialog(
54 | JavaBundle.message("generate.tostring.method.already.exists.dialog.me=ssage", targetMethodName),
55 | JavaBundle.message("generate.tostring.method.already.exists.dialog.title"), Messages.getQuestionIcon());
56 | if (exit == Messages.CANCEL) {
57 | return CancelPolicy.getInstance();
58 | }
59 | if (exit == Messages.YES) {
60 | return ReplacePolicy.getInstance();
61 | }
62 | if (exit == Messages.NO) {
63 | return DuplicatePolicy.getInstance();
64 | }
65 |
66 | throw new IllegalArgumentException("exit code [" + exit + "] from YesNoCancelDialog not supported");
67 | }
68 |
69 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/configurable/SingleFileExecutionConfig.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.configurable;
2 |
3 | import com.intellij.openapi.components.*;
4 | import com.intellij.openapi.project.Project;
5 | import com.intellij.util.xmlb.XmlSerializerUtil;
6 | import org.jetbrains.annotations.Nullable;
7 |
8 | @State(
9 | name="SingleFileExecutionConfig",
10 | storages = {
11 | @Storage("SingleFileExecutionConfig.xml")}
12 | )
13 | @Service
14 | public class SingleFileExecutionConfig implements PersistentStateComponent {
15 | /* NOTE: member should be "public" to be saved in xml */
16 | /* add_executable(): exe name */
17 | static final String EXECUTABLE_NAME_FILENAME = "%FILENAME%";
18 | public static final String DEFAULT_EXECUTABLE_NAME = EXECUTABLE_NAME_FILENAME;
19 | public String executableName = DEFAULT_EXECUTABLE_NAME; // persistent member should be public
20 | /* set_target_properties(): runtime output directory */
21 | static final String PROJECTDIR = "%PROJECTDIR%";
22 | static final String FILEDIR = "%FILEDIR%";
23 | public static final String DEFAULT_RUNTIME_OUTPUT_DIRECTORY = "";
24 | public String runtimeOutputDirectory = ""; // set empty string as default, persistent member should be public
25 | private static final boolean DEFAULT_NOT_SHOW_OVERWRITE_CONFIRM_DIALOG = false;
26 | public boolean notShowOverwriteConfirmDialog = DEFAULT_NOT_SHOW_OVERWRITE_CONFIRM_DIALOG; // persistent member should be public
27 |
28 | SingleFileExecutionConfig() { }
29 |
30 | String getExecutableName() {
31 | if (executableName == null) {
32 | // Error, it should not happen
33 | executableName = "";
34 | }
35 | return executableName;
36 | }
37 |
38 | void setExecutableName(String executableName) {
39 | this.executableName = executableName;
40 | }
41 |
42 | public String getRuntimeOutputDirectory() {
43 | return runtimeOutputDirectory;
44 | }
45 |
46 | public void setRuntimeOutputDirectory(String runtimeOutputDirectory) {
47 | this.runtimeOutputDirectory = runtimeOutputDirectory;
48 | }
49 |
50 | @Nullable
51 | @Override
52 | public SingleFileExecutionConfig getState() {
53 | return this;
54 | }
55 |
56 | @Override
57 | public void loadState(SingleFileExecutionConfig singleFileExecutionConfig) {
58 | XmlSerializerUtil.copyBean(singleFileExecutionConfig, this);
59 | }
60 |
61 | @Nullable
62 | public static SingleFileExecutionConfig getInstance(Project project) {
63 | SingleFileExecutionConfig sfec = ServiceManager.getService(project, SingleFileExecutionConfig.class);
64 | return sfec;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/ComparingReferencesInspection/src/test/java/com/lkl/plugin/ComparingReferencesInspectionTest.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. and other contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 |
3 | package com.lkl.plugin;
4 |
5 | import com.intellij.codeInsight.daemon.impl.HighlightInfo;
6 | import com.intellij.codeInsight.intention.IntentionAction;
7 | import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
8 | import org.jetbrains.annotations.NotNull;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * Class for testing ComparingReferencesInspection.
14 | * Requires idea.home.path to be set in build.gradle
15 | * doTest() does the work for individual test cases.
16 | */
17 | public class ComparingReferencesInspectionTest extends LightJavaCodeInsightFixtureTestCase {
18 |
19 | /**
20 | * Defines path to files used for running tests
21 | *
22 | * @return The path from this module's root directory ($MODULE_WORKING_DIR$) to the
23 | * directory containing files for these tests.
24 | */
25 | @Override
26 | protected String getTestDataPath() {
27 | return "src/test/testData";
28 | }
29 |
30 | /**
31 | * Given the name of a test file, runs comparing references inspection quick fix and tests
32 | * the results against a reference outcome file. File name pattern 'foo.java' and 'foo.after.java'
33 | * are matching before and after files in the testData directory.
34 | *
35 | * @param testName The name of the test file before comparing references inspection.
36 | */
37 | protected void doTest(@NotNull String testName) {
38 | // Initialize the test based on the testData file
39 | myFixture.configureByFile(testName + ".java");
40 | // Initialize the inspection and get a list of highlighted
41 | myFixture.enableInspections(new ComparingReferencesInspection());
42 | List highlightInfos = myFixture.doHighlighting();
43 | assertFalse(highlightInfos.isEmpty());
44 | // Get the quick fix action for comparing references inspection and apply it to the file
45 | final IntentionAction action = myFixture.findSingleIntention(ComparingReferencesInspection.QUICK_FIX_NAME);
46 | assertNotNull(action);
47 | myFixture.launchAction(action);
48 | // Verify the results
49 | myFixture.checkResultByFile(testName + ".after.java");
50 | }
51 |
52 | /**
53 | * Test the "==" case
54 | */
55 | public void testRelationalEq() throws Throwable {
56 | doTest("Eq");
57 | }
58 |
59 | /**
60 | * Test the "!=" case
61 | */
62 | public void testRelationalNeq() throws Throwable {
63 | doTest("Neq");
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/GenerateToStringConfigurable.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2000-2012 JetBrains s.r.o.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring;
17 |
18 | import com.intellij.java.JavaBundle;
19 | import com.intellij.openapi.diagnostic.Logger;
20 | import com.intellij.openapi.options.Configurable;
21 | import com.intellij.openapi.options.ConfigurationException;
22 | import com.intellij.openapi.project.Project;
23 | import org.jetbrains.java.generate.GenerateToStringContext;
24 | import org.jetbrains.java.generate.config.Config;
25 | import org.jetbrains.java.generate.view.ConfigUI;
26 |
27 | import javax.swing.*;
28 |
29 | /**
30 | * @author yole
31 | */
32 | public class GenerateToStringConfigurable implements Configurable {
33 | private static final Logger log = Logger.getInstance("#GenerateToStringConfigurable");
34 |
35 | private ConfigUI configUI;
36 | private final Project myProject;
37 |
38 | public GenerateToStringConfigurable(Project project) {
39 | myProject = project;
40 | }
41 |
42 | @Override
43 | public String getDisplayName() {
44 | return JavaBundle.message("configurable.GenerateToStringConfigurable.display.name");
45 | }
46 |
47 | @Override
48 | public String getHelpTopic() {
49 | return "editing.altInsert.tostring.settings";
50 | }
51 |
52 | @Override
53 | public JComponent createComponent() {
54 | return configUI = new ConfigUI(GenerateToStringContext.getConfig(), myProject);
55 | }
56 |
57 | @Override
58 | public boolean isModified() {
59 | return ! GenerateToStringContext.getConfig().equals(configUI.getConfig());
60 | }
61 |
62 | @Override
63 | public void apply() throws ConfigurationException {
64 | Config config = configUI.getConfig();
65 | GenerateToStringContext.setConfig(config); // update context
66 |
67 | if (log.isDebugEnabled()) log.debug("Config updated:\n" + config);
68 | }
69 |
70 | @Override
71 | public void reset() {
72 | configUI.setConfig(GenerateToStringContext.getConfig());
73 | }
74 |
75 | @Override
76 | public void disposeUIResources() {
77 | configUI = null;
78 | }
79 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/ui/CodeGeneratorConfigurable.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.ui;
2 |
3 | import com.intellij.openapi.components.ServiceManager;
4 | import com.intellij.openapi.options.ConfigurationException;
5 | import com.intellij.openapi.options.SearchableConfigurable;
6 | import com.lkl.plugin.codegenerator.config.CodeGeneratorSettings;
7 | import com.lkl.plugin.codegenerator.config.CodeTemplate;
8 | import org.jetbrains.annotations.Nls;
9 | import org.jetbrains.annotations.NotNull;
10 | import org.jetbrains.annotations.Nullable;
11 |
12 | import javax.swing.*;
13 | import java.util.List;
14 | import java.util.Optional;
15 |
16 | public class CodeGeneratorConfigurable implements SearchableConfigurable {
17 | private CodeGeneratorSettings settings;
18 | private CodeGeneratorConfig config;
19 |
20 | public CodeGeneratorConfigurable() {
21 | this.settings = ServiceManager.getService(CodeGeneratorSettings.class);
22 | }
23 |
24 | @NotNull @Override public String getId() {
25 | return "plugins.codegenerator";
26 | }
27 |
28 | @Nls @Override public String getDisplayName() {
29 | return "CodeGenerator";
30 | }
31 |
32 | @Nullable
33 | @Override
34 | public String getHelpTopic() {
35 | return null;
36 | }
37 |
38 | @Nullable @Override public JComponent createComponent() {
39 | if (config == null) {
40 | config = new CodeGeneratorConfig(settings);
41 | }
42 | return config.getMainPane();
43 | }
44 |
45 | @Override public boolean isModified() {
46 | if (config == null) {
47 | return false;
48 | }
49 |
50 | List templates = config.getTabTemplates();
51 | if (settings.getCodeTemplates().size() != templates.size()) {
52 | return true;
53 | }
54 |
55 | for (CodeTemplate template: templates) {
56 | Optional codeTemplate = settings.getCodeTemplate(template.getId());
57 | if (!codeTemplate.isPresent() || !codeTemplate.get().equals(template)) {
58 | return true;
59 | }
60 | }
61 |
62 | return false;
63 | }
64 |
65 | @Override public void apply() throws ConfigurationException {
66 | List templates = config.getTabTemplates();
67 | for (CodeTemplate template : templates) {
68 | if (!template.isValid()) {
69 | throw new ConfigurationException(
70 | "Not property can be empty and classNumber should be a number");
71 | }
72 | }
73 |
74 | settings.setCodeTemplates(templates);
75 | config.refresh(templates);
76 | }
77 |
78 | @Override
79 | public void reset() {
80 |
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/ui/ClassSelectionPane.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.ui;
2 |
3 | import com.intellij.uiDesigner.core.GridConstraints;
4 | import com.intellij.uiDesigner.core.GridLayoutManager;
5 | import com.intellij.uiDesigner.core.Spacer;
6 | import com.lkl.plugin.codegenerator.config.ClassSelectionConfig;
7 |
8 | import javax.swing.*;
9 | import javax.swing.border.TitledBorder;
10 | import java.awt.*;
11 |
12 | public class ClassSelectionPane implements PipelineStepConfig {
13 | private JPanel topPane;
14 | private JTextField initialClassText;
15 |
16 | public ClassSelectionPane(ClassSelectionConfig config) {
17 | initialClassText.setText(config.initialClass);
18 | }
19 |
20 | @Override
21 | public ClassSelectionConfig getConfig() {
22 | ClassSelectionConfig config = new ClassSelectionConfig();
23 | config.initialClass = initialClassText.getText();
24 | return config;
25 | }
26 |
27 | @Override
28 | public JPanel getComponent() {
29 | return topPane;
30 | }
31 |
32 | {
33 | // GUI initializer generated by IntelliJ IDEA GUI Designer
34 | // >>> IMPORTANT!! <<<
35 | // DO NOT EDIT OR ADD ANY CODE HERE!
36 | $$$setupUI$$$();
37 | }
38 |
39 | /**
40 | * Method generated by IntelliJ IDEA GUI Designer
41 | * >>> IMPORTANT!! <<<
42 | * DO NOT edit this method OR call it in your code!
43 | *
44 | * @noinspection ALL
45 | */
46 | private void $$$setupUI$$$() {
47 | topPane = new JPanel();
48 | topPane.setLayout(new GridLayoutManager(2, 2, new Insets(0, 0, 0, 0), -1, -1));
49 | topPane.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(), null, TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, null, null));
50 | initialClassText = new JTextField();
51 | topPane.add(initialClassText, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
52 | final Spacer spacer1 = new Spacer();
53 | topPane.add(spacer1, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
54 | final JLabel label1 = new JLabel();
55 | label1.setText("Initial Class");
56 | topPane.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
57 | }
58 |
59 | /**
60 | * @noinspection ALL
61 | */
62 | public JComponent $$$getRootComponent$$$() {
63 | return topPane;
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/config/InsertAfterEqualsHashCodeStrategy.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.config;
17 |
18 | import com.intellij.openapi.editor.Editor;
19 | import com.intellij.psi.PsiClass;
20 | import com.intellij.psi.PsiMethod;
21 | import org.jetbrains.annotations.NotNull;
22 | import org.jetbrains.java.generate.config.InsertNewMethodStrategy;
23 | import org.jetbrains.java.generate.psi.PsiAdapter;
24 |
25 | /**
26 | * Inserts the method after the hashCode/equals methods in the javafile.
27 | */
28 | public final class InsertAfterEqualsHashCodeStrategy implements InsertNewMethodStrategy {
29 |
30 | private static final InsertAfterEqualsHashCodeStrategy instance = new InsertAfterEqualsHashCodeStrategy();
31 |
32 | private InsertAfterEqualsHashCodeStrategy() {}
33 |
34 | public static InsertAfterEqualsHashCodeStrategy getInstance() {
35 | return instance;
36 | }
37 |
38 | @Override
39 | public PsiMethod insertNewMethod(PsiClass clazz, @NotNull PsiMethod newMethod, Editor editor) {
40 | PsiMethod methodHashCode = PsiAdapter.findHashCodeMethod(clazz);
41 | PsiMethod methodEquals = PsiAdapter.findEqualsMethod(clazz);
42 |
43 | // if both methods exist determine the last method in the javafile
44 | PsiMethod method;
45 | if (methodEquals != null && methodHashCode != null) {
46 | if (methodEquals.getTextOffset() > methodHashCode.getTextOffset()) {
47 | method = methodEquals;
48 | } else {
49 | method = methodHashCode;
50 | }
51 | } else {
52 | method = methodHashCode != null ? methodHashCode : methodEquals;
53 | }
54 |
55 | if (method != null) {
56 | // insert after the equals/hashCode method
57 | newMethod = (PsiMethod) clazz.addAfter(newMethod, method);
58 | } else {
59 | // no equals/hashCode so insert at caret
60 | newMethod = InsertAtCaretStrategy.getInstance().insertNewMethod(clazz, newMethod, editor);
61 | }
62 |
63 | return newMethod;
64 | }
65 |
66 | public String toString() {
67 | return "After equals/hashCode";
68 | }
69 | }
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.lkl.plugin.MvpAutoCode
4 | MvpAutoCode
5 | lkl
6 |
7 | MvpAutoCodePlus
9 |
10 |
11 |
12 | Website |
13 | GitHub |
14 | Issues |
15 | Blog
16 |
17 |
18 |
19 | An plugin that automatically generates an MVP template code.
20 |
21 | Features:
22 |
23 | - Automatically generate Contract Interface based on the specified super Interface.
24 | - Automatically generate implements class based on the Contract Interface and specified superclass.Add the default implementation of the abstract method.
25 | - Supports generics(currently only have M,V,P).
26 | - Supports Java and Kotlin.
27 |
28 |
29 |
30 | Send feedback
31 | ]]>
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | org.jetbrains.kotlin
44 |
46 |
47 | com.intellij.modules.lang
48 | com.intellij.modules.java
49 | org.jetbrains.android
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/config/CodeGeneratorSettings.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.config;
2 |
3 | import com.intellij.openapi.components.PersistentStateComponent;
4 | import com.intellij.openapi.components.State;
5 | import com.intellij.openapi.components.Storage;
6 | import com.intellij.openapi.diagnostic.Logger;
7 | import com.intellij.openapi.util.io.FileUtil;
8 | import com.intellij.util.xmlb.XmlSerializerUtil;
9 | import org.jetbrains.annotations.Nullable;
10 |
11 | import java.io.IOException;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.Optional;
15 |
16 | @State(name = "CodeGeneratorSettings", storages = {@Storage("$APP_CONFIG$/CodeGeneratorSettings.xml")})
17 | public class CodeGeneratorSettings implements PersistentStateComponent {
18 |
19 | private static final Logger LOGGER = Logger.getInstance(CodeGeneratorSettings.class);
20 | private List codeTemplates;
21 |
22 | public CodeGeneratorSettings() {
23 |
24 | }
25 |
26 | public CodeGeneratorSettings setCodeTemplates(List codeTemplates) {
27 | this.codeTemplates = codeTemplates;
28 | return this;
29 | }
30 |
31 |
32 | @Nullable @Override public CodeGeneratorSettings getState() {
33 | if (codeTemplates == null) {
34 | codeTemplates = loadDefaultTemplates();
35 | }
36 | return this;
37 | }
38 |
39 | @Override public void loadState(CodeGeneratorSettings codeGeneratorSettings) {
40 | XmlSerializerUtil.copyBean(codeGeneratorSettings, this);
41 | }
42 |
43 | public List getCodeTemplates() {
44 | if (codeTemplates == null) {
45 | codeTemplates = loadDefaultTemplates();
46 | }
47 | return codeTemplates;
48 | }
49 |
50 | public Optional getCodeTemplate(String templateId) {
51 | return codeTemplates.stream()
52 | .filter(t -> t!= null && t.getId().equals(templateId))
53 | .findFirst();
54 | }
55 |
56 | public void removeCodeTemplate(String templateId) {
57 | codeTemplates.removeIf(template -> template.name.equals(templateId));
58 | }
59 |
60 | private List loadDefaultTemplates() {
61 | List templates = new ArrayList<>();
62 | try {
63 | templates.addAll(loadTemplates("getters-and-setters.xml"));
64 | templates.addAll(loadTemplates("to-string.xml"));
65 | templates.addAll(loadTemplates("HUE-Serialization.xml"));
66 | } catch (Exception e) {
67 | LOGGER.error("loadDefaultTemplates failed", e);
68 | }
69 | return templates;
70 | }
71 |
72 | private List loadTemplates(String templateFileName) throws IOException {
73 | return CodeTemplateList.fromXML(FileUtil.loadTextAndClose(CodeGeneratorSettings.class.getResourceAsStream("/template/" + templateFileName)));
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/docs/psi/psiAugmentProvider.md:
--------------------------------------------------------------------------------
1 | # PsiAugmentProvider
2 |
3 | * [简介](#简介)
4 | * [重写getAugments方法](#重写getaugments方法)
5 | * [参考文献](#参考文献)
6 |
7 | ## 简介
8 | 对于这个类,IDEA中提供的说明是:有些代码不是它看起来的样子!这种扩展允许插件增强现实,改变Java PSI元素的行为。
9 |
10 | IDEA中所有文件以及文件中的内容都是用PSI树来表示的,比如类表示为PsiClass,方法表示为PsiMethod,字段表示为PsiField。我们可以通过更改PSI来做到动态的添加字段,方法等。
11 |
12 | 上面说的比较抽象,我们来举一个简单的例子,还是以Lombok为例。了解Lombok原理的同学都知道,Lombok利用的是javac技术,就是在java文件编译的时候动态的将getter,setter等方法生成到class文件中。
13 |
14 | 这种方式就出带来一个问题,由于getter和setter方法在编译的时候才会动态生成,实际运行时不会有任务问题;但是在IDEA中,编译检查时会发现没有对应的setter或者getter方法,就会出现“标红”,提示没有该字段或者方法。
15 |
16 | 其实这时就应该清楚了,我们可以通过继承PsiAugmentProvider这个类,通过扩展PSI,动态的为该类中新增相应的“虚拟”的getter或者setter方法。以此来解决“标红”问题。
17 |
18 | 这时在编辑框中是没有通过PsiAugmentProvider扩展的这些方法,但是实际调用的时候却有,这也就是上述所说的:有些代码不是它看起来的样子!
19 |
20 | > 动态扩展的PSI方法或者字段,在编译时不会生成。在进行扩展方法时,只需要生成具体的方法签名即可~不需要关注具体的实现细节。
21 |
22 | ## 重写getAugments方法
23 |
24 | 通过重写`getAugments`方法可以扩展每个文件的`PSI`,即实现动态的扩展相应的方法或者字段。
25 |
26 | `getAugments`中会传入两个参数,分别为`PsiElement psiElement`和`Class type`:
27 |
28 | * **PsiElement**是PSI系统下不同类型对象的一个统称,是基类;比如之前提到的`PsiMethod`、`PsiClass`等等都是一个个具体的`PsiElement`的实现。
29 | * **Class type**,type类型可以用于判断具体是`PsiMethod`还是`PsiClass`,进行分开处理。
30 |
31 | 在getAugments中进行扩展相应方法时,需要借助IDEA中提供的`LightMethodBuilder`类。通过设置方法名,方法的修饰符,方法的返回值,方法的传入即可添加一个方法。
32 |
33 | 比如现在需要为`mobile`字段,添加set方法,那么具体的代码为:
34 | ```java
35 | PsiManager manager = psiField.getManager();
36 | LightMethodBuilder method = new LightMethodBuilder(manager, JavaLanguage.INSTANCE, methodName);
37 | method.addModifier(PsiModifier.PUBLIC);
38 | method.setContainingClass(psiClass);
39 | method.setNavigationElement(psiField);
40 | method.addParameter(psiField.getName(), psiField.getType());
41 | method.setMethodReturnType(PsiType.VOID);
42 | ```
43 |
44 | 在getAugments中进行扩展相应字段时,需要借助IDEA中提供的`LightFieldBuilder`类。同样通过设置字段名,字段的修饰符即可添加一个字段。
45 |
46 | 比如现在需要添加 `private static final Logger logger`字段,那么具体的代码为:
47 | ```java
48 | PsiType psiLoggerType = psiElementFactory.createTypeFromText(LOGGER_TYPE, psiClass);
49 | LightFieldBuilder loggerField = new LightFieldBuilder(manager, LOGGER_NAME, psiLoggerType);
50 | LightModifierList modifierList = (LightModifierList) loggerField.getModifierList();
51 | modifierList.addModifier(PsiModifier.PRIVATE);
52 | modifierList.addModifier(PsiModifier.STATIC);
53 | modifierList.addModifier(PsiModifier.FINAL);
54 | loggerField.setContainingClass(psiClass);
55 | loggerField.setNavigationElement(psiAnnotation);
56 | ```
57 |
58 | 在`PsiAugmentProvider`中,对于每个生成的`method`和`field`,都需要加入到`Cache`当中,以此来保证每次获取时候的性能~在IDEA插件开发当中可以选择其提供的`CachedValuesManager`~
59 |
60 | ## 参考文献
61 |
62 | [IntelliJ IDEA插件开发指南(二)](https://blog.csdn.net/ExcellentYuXiao/article/details/80273347)
63 |
64 | [Class PsiAugmentProvider](https://dploeger.github.io/intellij-api-doc/com/intellij/psi/augment/PsiAugmentProvider.html)
65 |
66 | [Java Code Examples for com.intellij.psi.augment.PsiAugmentProvider](https://www.programcreek.com/java-api-examples/index.php?api=com.intellij.psi.augment.PsiAugmentProvider)
67 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/velocity/VelocityFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2007 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.velocity;
17 |
18 | import com.intellij.codeInsight.generation.VelocityIncludesClassLoader;
19 | import com.intellij.openapi.util.ClassLoaderUtil;
20 | import org.apache.commons.collections.ExtendedProperties;
21 | import org.apache.velocity.app.VelocityEngine;
22 | import org.apache.velocity.runtime.RuntimeConstants;
23 | import org.apache.velocity.runtime.log.SimpleLog4JLogSystem;
24 |
25 | /**
26 | * Velocity factory.
27 | *
28 | * Creating instances of the VelocityEngine.
29 | */
30 | public final class VelocityFactory {
31 | private static class Holder {
32 | private static final VelocityEngine engine = newVelocityEngine();
33 | }
34 |
35 | /**
36 | * Privte constructor.
37 | */
38 | private VelocityFactory() {
39 | }
40 |
41 | /**
42 | * Returns a new instance of the VelocityEngine.
43 | *
44 | * The engine is initialized and outputs its logging to IDEA logging.
45 | *
46 | * @return a new velocity engine that is initialized.
47 | */
48 | private static VelocityEngine newVelocityEngine() {
49 | ExtendedProperties prop = new ExtendedProperties();
50 | prop.addProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, SimpleLog4JLogSystem.class.getName());
51 | prop.addProperty("runtime.log.logsystem.log4j.category", "GenerateToString");
52 | prop.addProperty(RuntimeConstants.RESOURCE_LOADER, "includes");
53 | prop.addProperty("includes.resource.loader.class", VelocityIncludesClassLoader.class.getName());
54 | prop.addProperty(RuntimeConstants.VM_PERM_ALLOW_INLINE_REPLACE_GLOBAL, "true");
55 |
56 | VelocityEngine velocity = new VelocityEngine();
57 | velocity.setExtendedProperties(prop);
58 | ClassLoaderUtil.runWithClassLoader(VelocityIncludesClassLoader.class.getClassLoader(), () -> velocity.init());
59 | return velocity;
60 | }
61 |
62 | /**
63 | * Get's a shared instance of the VelocityEngine.
64 | *
65 | * The engine is initialized and outputs its logging to IDEA logging.
66 | *
67 | * @return a shared instance of the engine that is initialized.
68 | */
69 | public static VelocityEngine getVelocityEngine() {
70 | return Holder.engine;
71 | }
72 | }
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/kotlin/com/lkl/plugin/maker/CodeMaker.kt:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.maker
2 |
3 | import com.intellij.ide.actions.CreateFileAction
4 | import com.intellij.ide.fileTemplates.FileTemplate
5 | import com.intellij.ide.fileTemplates.FileTemplateManager
6 | import com.intellij.ide.fileTemplates.FileTemplateUtil
7 | import com.intellij.ide.fileTemplates.actions.CreateFromTemplateActionBase
8 | import com.intellij.ide.util.PropertiesComponent
9 | import com.intellij.openapi.fileEditor.FileEditorManager
10 | import com.intellij.psi.PsiDirectory
11 | import com.intellij.psi.PsiFile
12 | import com.intellij.psi.SmartPointerManager
13 | import com.intellij.util.IncorrectOperationException
14 | import org.apache.velocity.runtime.parser.ParseException
15 |
16 | /**
17 | * Created by XQ Yang on 2018/6/28 15:34.
18 | * Description : 创建对应的源文件
19 | */
20 | fun createFileFromTemplate(fileName: String?,
21 | template: FileTemplate,
22 | d: PsiDirectory,
23 | defaultTemplateProperty: String?,
24 | openFile: Boolean,
25 | liveTemplateDefaultValues: Map,
26 | author: String?): PsiFile? {
27 | var name = fileName
28 | var dir = d
29 | if (name != null) {
30 | val mkdirs = CreateFileAction.MkDirs(name, dir)
31 | name = mkdirs.newName
32 | dir = mkdirs.directory
33 | }
34 |
35 | val project = dir.project
36 | try {
37 | val defaultProperties = FileTemplateManager.getInstance(dir.project).defaultProperties
38 | defaultProperties.putAll(liveTemplateDefaultValues)
39 | if (!author.isNullOrEmpty()) {
40 | defaultProperties["USER"] = author
41 | }
42 | val psiFile = FileTemplateUtil.createFromTemplate(template, name, defaultProperties, dir)
43 | .containingFile
44 | val pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(psiFile)
45 |
46 | val virtualFile = psiFile.virtualFile
47 | if (virtualFile != null) {
48 | if (openFile) {
49 | if (template.isLiveTemplateEnabled) {
50 | CreateFromTemplateActionBase.startLiveTemplate(psiFile, liveTemplateDefaultValues)
51 | } else {
52 | FileEditorManager.getInstance(project).openFile(virtualFile, true)
53 | }
54 | }
55 | if (defaultTemplateProperty != null) {
56 | PropertiesComponent.getInstance(project).setValue(defaultTemplateProperty, template.name)
57 | }
58 | return pointer.element
59 | }
60 | } catch (e: ParseException) {
61 | throw IncorrectOperationException("Error parsing Velocity template: " + e.message, e as Throwable)
62 | } catch (e: IncorrectOperationException) {
63 | throw e
64 | } catch (e: Exception) {
65 | e.printStackTrace()
66 | }
67 |
68 | return null
69 | }
70 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/util/EntryUtils.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.util;
2 |
3 | import com.intellij.psi.PsiField;
4 | import com.intellij.psi.PsiMember;
5 | import com.intellij.psi.PsiMethod;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Collection;
9 | import java.util.List;
10 |
11 | public class EntryUtils {
12 | public static List getOnlyAsFieldAndMethodElements(Collection extends PsiMember> members,
13 | Collection extends PsiMember> selectedNotNullMembers,
14 | boolean useAccessors) {
15 | List
16 | entryList = new ArrayList<>();
17 |
18 | for (PsiMember member : members) {
19 | MemberEntry entry = null;
20 | if (member instanceof PsiField) {
21 | FieldEntry fieldEntry= EntryFactory.of((PsiField) member, useAccessors);
22 | if (selectedNotNullMembers.contains(member)) {
23 | fieldEntry.setNotNull(true);
24 | }
25 | entry = fieldEntry;
26 | } else if (member instanceof PsiMethod) {
27 | MethodEntry methodEntry = EntryFactory.of((PsiMethod) member);
28 | if (selectedNotNullMembers.contains(member)) {
29 | methodEntry.setNotNull(true);
30 | }
31 | entry = methodEntry;
32 | }
33 |
34 | if (entry != null) {
35 | entryList.add(entry);
36 | }
37 | }
38 | return entryList;
39 | }
40 |
41 | public static List getOnlyAsFieldEntries(Collection extends PsiMember> members,
42 | Collection extends PsiMember> selectedNotNullMembers,
43 | boolean useAccessors) {
44 | List fieldEntryList = new ArrayList<>();
45 |
46 | for (PsiMember member : members) {
47 | if (member instanceof PsiField) {
48 | PsiField field = (PsiField) member;
49 | FieldEntry fe = EntryFactory.of(field, useAccessors);
50 | if (selectedNotNullMembers.contains(member)) {
51 | fe.setNotNull(true);
52 | }
53 | fieldEntryList.add(fe);
54 | }
55 | }
56 |
57 | return fieldEntryList;
58 | }
59 |
60 | public static List getOnlyAsMethodEntrys(Collection extends PsiMember> members) {
61 | List methodEntryList = new ArrayList<>();
62 |
63 | for (PsiMember member : members) {
64 | if (member instanceof PsiMethod) {
65 | PsiMethod method = (PsiMethod) member;
66 | MethodEntry me = EntryFactory.of(method);
67 | methodEntryList.add(me);
68 | }
69 | }
70 |
71 | return methodEntryList;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/ui/SelectionPane.form:
--------------------------------------------------------------------------------
1 |
2 |
61 |
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/kotlin/com/lkl/plugin/maker/TemplateMaker.kt:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.maker
2 |
3 | import com.intellij.ide.fileTemplates.FileTemplate
4 | import com.intellij.ide.fileTemplates.FileTemplateManager
5 | import com.intellij.ide.fileTemplates.FileTemplateUtil
6 | import com.intellij.ide.fileTemplates.impl.FileTemplateManagerImpl
7 | import com.intellij.openapi.project.Project
8 | import com.lkl.plugin.*
9 |
10 | /**
11 | * Created by XQ Yang on 2018/6/28 10:46.
12 | * Description : template管理类
13 | */
14 |
15 | object TemplateMaker {
16 |
17 | var tpManager: FileTemplateManagerImpl? = null
18 | val cacheTemplate = HashMap()
19 |
20 |
21 | private fun createContractTemplate(name: String, type: String, content: String) {
22 | val template = FileTemplateUtil.createTemplate(name, type, content,
23 | tpManager!!.getTemplates(FileTemplateManager.DEFAULT_TEMPLATES_CATEGORY))
24 | template.isLiveTemplateEnabled = false
25 | //保存到ide中,这里就不保存了
26 | // tpManager.setTemplates(FileTemplateManager.DEFAULT_TEMPLATES_CATEGORY, listOf(template))
27 | cacheTemplate[name] = template
28 | }
29 |
30 | fun getTemplate(templateName: String, project: Project): FileTemplate? {
31 | if (cacheTemplate.contains(templateName)) {
32 | return cacheTemplate[templateName] as FileTemplate
33 | } else if (tpManager == null) {
34 | tpManager = FileTemplateManagerImpl.getInstanceImpl(project)
35 | }
36 |
37 | when (templateName) {
38 | CONTRACT_TP_NAME_JAVA -> createContractTemplate(templateName, "java", TemplateCons.CONTRACT_TP_CONTENT_JAVA)
39 | CONTRACT_TP_NAME_KOTLIN -> createContractTemplate(templateName, "kt", TemplateCons.CONTRACT_TP_CONTENT_KOTLIN)
40 | CONTRACT_TP_NO_MODEL_NAME_JAVA -> createContractTemplate(templateName, "java", TemplateCons.CONTRACT_TP_CONTENT_NO_MODEL_JAVA)
41 | CONTRACT_TP_NO_MODEL_NAME_KOTLIN -> createContractTemplate(templateName, "kt", TemplateCons.CONTRACT_TP_CONTENT_NO_MODEL_KOTLIN)
42 | VIEW_IMPL_TP_ACTIVITY_JAVA -> createContractTemplate(templateName, "java", TemplateCons.COMMON_IMPL_TP_CONTENT_JAVA)
43 | VIEW_IMPL_TP_FRAGMENT_JAVA -> createContractTemplate(templateName, "java", TemplateCons.COMMON_IMPL_TP_CONTENT_JAVA)
44 | PRESENTER_IMPL_TP_JAVA -> createContractTemplate(templateName, "java", TemplateCons.COMMON_IMPL_TP_CONTENT_JAVA)
45 | MODEL_IMPL_TP_JAVA -> createContractTemplate(templateName, "java", TemplateCons.COMMON_IMPL_TP_CONTENT_JAVA)
46 | VIEW_IMPL_TP_ACTIVITY_KOTLIN -> createContractTemplate(templateName, "kt", TemplateCons.COMMON_IMPL_TP_CONTENT_KOTLIN)
47 | VIEW_IMPL_TP_FRAGMENT_KOTLIN -> createContractTemplate(templateName, "kt", TemplateCons.COMMON_IMPL_TP_CONTENT_KOTLIN)
48 | PRESENTER_IMPL_TP_KOTLIN -> createContractTemplate(templateName, "kt", TemplateCons.COMMON_IMPL_TP_CONTENT_KOTLIN)
49 | MODEL_IMPL_TP_KOTLIN -> createContractTemplate(templateName, "kt", TemplateCons.COMMON_IMPL_TP_CONTENT_KOTLIN)
50 | }
51 |
52 | return if (cacheTemplate.containsKey(templateName)) cacheTemplate[templateName] as FileTemplate else null
53 | }
54 |
55 |
56 | }
57 |
58 |
59 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/resources/template/to-string.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | df5bbb3e-4465-4474-8920-2316a5df67c4
6 | ToString
7 | .*\.java$
8 | body
9 | false
10 | public java.lang.String toString() {
11 | #if ( $members.size() > 0 )
12 | #set ( $i = 0 )
13 | return "$class0.name{" +
14 | #foreach( $member in $members )
15 | #if ( $i == 0 )
16 | "##
17 | #else
18 | ", ##
19 | #end
20 | #if ( $member.objectArray )
21 | #if ($java_version < 5)
22 | $member.name=" + ($member.accessor == null ? null : java.util.Arrays.asList($member.accessor)) +
23 | #else
24 | $member.name=" + java.util.Arrays.toString($member.accessor) +
25 | #end
26 | #elseif ( $member.primitiveArray && $java_version >= 5)
27 | $member.name=" + java.util.Arrays.toString($member.accessor) +
28 | #elseif ( $member.string )
29 | $member.name='" + $member.accessor + '\'' +
30 | #else
31 | $member.name=" + $member.accessor +
32 | #end
33 | #set ( $i = $i + 1 )
34 | #end
35 | '}';
36 | #else
37 | return "$class0.name{}";
38 | #end
39 | }
40 | UTF-8
41 |
42 |
43 | true
44 | false
45 | false
46 | true
47 | true
48 |
49 |
50 |
51 |
52 | false
53 | ## set `availableMembers` to provide the members to select
54 | ## set `selectedMembers` to select the members initially, set nothing to select all
55 | ## Note that it should be type List<PsiMember> or List<MemberEntry>
56 | ## And the selected result will be
57 | ## - fields1: List<FieldEntry> where `1` is the step number that you specified
58 | ## - methods1: List<MethodEntry>
59 | ## - members: List<MemberEntry>
60 | #set($availableMembers = $class0.members)
61 |
62 | true
63 | true
64 | 0
65 | 1
66 | true
67 |
68 |
69 | AT_CARET
70 | ASK
71 | true
72 | $class0.name
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/action/CodeGeneratorGroup.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.action;
2 |
3 | import com.intellij.openapi.actionSystem.*;
4 | import com.intellij.openapi.components.ServiceManager;
5 | import com.intellij.openapi.editor.Caret;
6 | import com.intellij.openapi.project.DumbAware;
7 | import com.intellij.openapi.project.Project;
8 | import com.intellij.psi.PsiClass;
9 | import com.intellij.psi.PsiElement;
10 | import com.intellij.psi.PsiFile;
11 | import com.intellij.psi.util.PsiTreeUtil;
12 | import com.lkl.plugin.codegenerator.config.CodeGeneratorSettings;
13 | import com.lkl.plugin.codegenerator.config.CodeTemplate;
14 | import org.jetbrains.annotations.NotNull;
15 | import org.jetbrains.annotations.Nullable;
16 |
17 | import java.util.List;
18 | import java.util.stream.Collectors;
19 |
20 | public class CodeGeneratorGroup extends ActionGroup implements DumbAware {
21 | private CodeGeneratorSettings settings;
22 |
23 | public CodeGeneratorGroup() {
24 | settings = ServiceManager.getService(CodeGeneratorSettings.class);
25 | }
26 |
27 | @Override
28 | public boolean hideIfNoVisibleChildren() {
29 | return false;
30 | }
31 |
32 | @NotNull @Override public AnAction[] getChildren(@Nullable AnActionEvent anActionEvent) {
33 | if (anActionEvent == null) {
34 | return AnAction.EMPTY_ARRAY;
35 | }
36 |
37 | Project project = PlatformDataKeys.PROJECT.getData(anActionEvent.getDataContext());
38 | if (project == null) {
39 | return AnAction.EMPTY_ARRAY;
40 | }
41 |
42 | PsiFile file = anActionEvent.getData(CommonDataKeys.PSI_FILE);
43 | if (file == null) {
44 | return AnAction.EMPTY_ARRAY;
45 | }
46 |
47 | Caret caret = anActionEvent.getDataContext().getData(LangDataKeys.CARET);
48 | boolean isProjectView = caret == null;
49 |
50 | if (!isProjectView) {
51 | // EditorPopup menu
52 | PsiElement element = file.findElementAt(caret.getOffset());
53 | PsiClass clazz = PsiTreeUtil.getParentOfType(element, PsiClass.class, false);
54 | if (clazz == null) {
55 | // not inside a class
56 | return AnAction.EMPTY_ARRAY;
57 | }
58 | }
59 |
60 |
61 | String fileName = file.getName();
62 | final List children = settings.getCodeTemplates().stream()
63 | .filter(t -> !isProjectView || (t.type.equals("class") && isProjectView))
64 | .filter(t -> t.enabled && fileName.matches(t.fileNamePattern))
65 | .map(CodeGeneratorGroup::getOrCreateAction)
66 | .collect(Collectors.toList());
67 |
68 | return children.toArray(new AnAction[children.size()]);
69 | }
70 |
71 | private static AnAction getOrCreateAction(CodeTemplate template) {
72 | final String actionId = "CodeMaker.Menu.Action." + template.getId();
73 | AnAction action = ActionManager.getInstance().getAction(actionId);
74 | if (action == null) {
75 | action = new CodeGeneratorAction(template.getId(), template.name);
76 | ActionManager.getInstance().registerAction(actionId, action);
77 | }
78 | return action;
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
34 |
35 | @rem Find java.exe
36 | if defined JAVA_HOME goto findJavaFromJavaHome
37 |
38 | set JAVA_EXE=java.exe
39 | %JAVA_EXE% -version >NUL 2>&1
40 | if "%ERRORLEVEL%" == "0" goto init
41 |
42 | echo.
43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
44 | echo.
45 | echo Please set the JAVA_HOME variable in your environment to match the
46 | echo location of your Java installation.
47 |
48 | goto fail
49 |
50 | :findJavaFromJavaHome
51 | set JAVA_HOME=%JAVA_HOME:"=%
52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
53 |
54 | if exist "%JAVA_EXE%" goto init
55 |
56 | echo.
57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
58 | echo.
59 | echo Please set the JAVA_HOME variable in your environment to match the
60 | echo location of your Java installation.
61 |
62 | goto fail
63 |
64 | :init
65 | @rem Get command-line arguments, handling Windows variants
66 |
67 | if not "%OS%" == "Windows_NT" goto win9xME_args
68 |
69 | :win9xME_args
70 | @rem Slurp the command line arguments.
71 | set CMD_LINE_ARGS=
72 | set _SKIP=2
73 |
74 | :win9xME_args_slurp
75 | if "x%~1" == "x" goto execute
76 |
77 | set CMD_LINE_ARGS=%*
78 |
79 | :execute
80 | @rem Setup the command line
81 |
82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
83 |
84 | @rem Execute Gradle
85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
86 |
87 | :end
88 | @rem End local scope for the variables with windows NT shell
89 | if "%ERRORLEVEL%"=="0" goto mainEnd
90 |
91 | :fail
92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
93 | rem the _cmd.exe /c_ return code!
94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
95 | exit /b 1
96 |
97 | :mainEnd
98 | if "%OS%"=="Windows_NT" endlocal
99 |
100 | :omega
101 |
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/kotlin/com/lkl/plugin/TemplateCons.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin;
2 |
3 | /**
4 | * Created by XQ Yang on 2018/6/28 11:02.
5 | * @describe 模版常量
6 | */
7 |
8 | public interface TemplateCons {
9 |
10 | String CONTRACT_TP_CONTENT_JAVA =
11 | "#if (${PACKAGE_NAME} != \"\")package ${PACKAGE_NAME};#end\n" + "\n" + "import ${V};\n" + "import ${P};\n" + "import ${M};\n" + "/**\n" + " * @describe \n" +
12 | " * @author ${USER}\n" + " * @date ${DATE} ${TIME}\n" + " * \t\t\t\t\t\t\t\t - generate by MvpAutoCodePlus plugin.\n" + " */\n" + "\n" +
13 | "public interface I${NAME}Contract {\n" + " interface View extends ${VN}${VG}{}\n" + " interface ${P_OR_M} extends ${PN}${PG}{}\n" +
14 | " interface Model extends ${MN}${MG}{}\n" + "}\n";
15 | String CONTRACT_TP_CONTENT_NO_MODEL_JAVA =
16 | "#if (${PACKAGE_NAME} != \"\")package ${PACKAGE_NAME};#end\n" + "\n" + "import ${V};\n" + "import ${P};\n" + "/**\n" + " * @describe \n" + " * @author ${USER}\n" +
17 | " * @date ${DATE} ${TIME}\n" + " * \t\t\t\t\t\t\t\t - generate by MvpAutoCodePlus plugin.\n" + " */\n" + "\n" + "public interface I${NAME}Contract {\n" +
18 | " interface View extends ${VN}${VG}{}\n" + " interface ${P_OR_M} extends ${PN}${PG}{}\n" + "}\n";
19 |
20 | String CONTRACT_TP_CONTENT_KOTLIN =
21 | "#if (${PACKAGE_NAME} != \"\")package ${PACKAGE_NAME}#end\n" + "\n" + "import ${V}\n" + "import ${P}\n" + "import ${M}\n" + "/**\n" + " * @describe \n" +
22 | " * @author ${USER}\n" + " * @date ${DATE} ${TIME}\n" + " * \t\t\t\t\t\t\t\t - generate by MvpAutoCodePlus plugin.\n" + " */\n" + "\n" + "interface ${NAME} {\n" +
23 | " interface View : ${VN}${VG}{}\n" + " interface ${P_OR_M} : ${PN}${PG}{}\n" + " interface Model : ${MN}${MG}{}\n" + "}\n";
24 | String CONTRACT_TP_CONTENT_NO_MODEL_KOTLIN =
25 | "#if (${PACKAGE_NAME} != \"\")package ${PACKAGE_NAME}#end\n" + "\n" + "import ${V}\n" + "import ${P}\n" + "/**\n" + " * @describe \n" + " * @author ${USER}\n" +
26 | " * @date ${DATE} ${TIME}\n" + " * \t\t\t\t\t\t\t\t - generate by MvpAutoCodePlus plugin.\n" + " */\n" + "\n" + "interface ${NAME} {\n" +
27 | " interface View : ${VN}${VG}{}\n" + " interface ${P_OR_M} : ${PN}${PG}{}\n" + "}\n";
28 |
29 | String COMMON_IMPL_TP_CONTENT_JAVA =
30 | "#if (${PACKAGE_NAME} != \"\")package ${PACKAGE_NAME};#end\n" + "\n" + "import ${CONTRACT};\n" + "import ${PACKAGE_NAME}.R;\n" + "#if (${IMPL} != \"\")import ${IMPL};#end\n" + "\n" + "\n" + "/**\n" +
31 | " * @describe \n" + " * @author ${USER}\n" + " * @date ${DATE} ${TIME}\n" + " * \t\t\t\t\t\t\t\t - generate by MvpAutoCodePlus plugin.\n" + " */\n" + "\n" +
32 | "public class ${NAME}${IMPL_TYPE} #if(${IMPL}!=\"\") extends ${IMPL}${VG}#end implements I${NAME}Contract.${TYPE} {\n" + "\n" + "}\n" + "\n";
33 |
34 | //todo R文件的报名应该是清单里面的报名
35 |
36 | String COMMON_IMPL_TP_CONTENT_KOTLIN =
37 | "#if (${PACKAGE_NAME} != \"\")package ${PACKAGE_NAME}#end\n" + "\n" + "import ${CONTRACT}\n" + "import ${PACKAGE_NAME}.R\n" + "#if (${IMPL} != \"\")import ${IMPL}#end\n" + "\n" + "/**\n" +
38 | " * @describe \n" + " * @author ${USER}\n" + " * @date ${DATE} ${TIME}\n" + " * \t\t\t\t\t\t\t\t - generate by MvpAutoCodePlus plugin.\n" + " */\n" + "\n" +
39 | "class ${NAME}${IMPL_TYPE} :#if (${IMPL_NP} != \"\") ${IMPL_NP}${VG}(),#end ${CONTRACT_NP}.${TYPE} {\n" + "\n" + "}\n" + "\n";
40 | }
41 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/resources/template/getters-and-setters.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 58a3b5d1-3621-43b8-9c17-e725ceaedbdd
6 | Getter and Setter
7 | .*\.java$
8 | body
9 | false
10 | #foreach($field in $fields)
11 | #set($name = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field.element, $project))))
12 | #if ($field.boolean && $field.primitive)
13 | #set($getter = "is${name}")
14 | #else
15 | #set($getter = "get${name}")
16 | #end
17 | #set($setter = "set${name}")
18 | #if($field.modifierStatic)
19 | static ##
20 | #end
21 | $field.type ##
22 | ${getter}() {
23 | return $field.name;
24 | }
25 |
26 | #if($field.modifierStatic)
27 | static ##
28 | #end
29 | #set($paramName = $helper.getParamName($field.element, $project))
30 | void ${setter}($field.type $paramName) {
31 | #if ($field.name == $paramName)
32 | #if (!$field.modifierStatic)
33 | this.##
34 | #else
35 | $classname.##
36 | #end
37 | #end
38 | $field.name = $paramName;
39 | }
40 | #end
41 | UTF-8
42 |
43 |
44 | true
45 | false
46 | false
47 | true
48 | true
49 |
50 |
51 |
52 |
53 | false
54 | #set($availableMembers = [])
55 | #set($methodNames = [])
56 | #foreach($method in $class0.methods)
57 | $methodNames.add($method.methodName)
58 | #end
59 | #foreach($field in $class0.fields)
60 | #set($name = $StringUtil.capitalizeWithJavaBeanConvention($StringUtil.sanitizeJavaIdentifier($helper.getPropertyName($field.element, $project))))
61 | #if ($field.boolean && $field.primitive)
62 | #set($getter = "is${name}")
63 | #else
64 | #set($getter = "get${name}")
65 | #end
66 | #set($setter = "set${name}")
67 | #if (!$methodNames.contains($getter) || !$methodNames.contains($setter))
68 | $availableMembers.add($field)
69 | #end
70 | #end
71 |
72 | true
73 | false
74 | 0
75 | 1
76 | true
77 |
78 |
79 | AT_CARET
80 | ASK
81 | true
82 | $class0.name
83 | false
84 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/MvpAutoCode/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.3.72'
3 | repositories {
4 | maven { url 'https://maven.aliyun.com/repository/public' }
5 | google()
6 | mavenCentral()
7 | }
8 | dependencies {
9 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
10 | }
11 | }
12 |
13 | plugins {
14 | id 'org.jetbrains.intellij' version '0.4.2'
15 | }
16 |
17 | version '1.4.3'
18 | group 'com.lkl.plugin'
19 |
20 | apply plugin: 'java'
21 | apply plugin: 'kotlin'
22 | apply plugin: 'kotlin-kapt'
23 | apply plugin: 'org.jetbrains.intellij'
24 |
25 | sourceCompatibility = 1.8
26 | targetCompatibility = 1.8
27 |
28 | //sourceSets {
29 | // main {
30 | // java {
31 | // srcDir "${project.rootDir.absolutePath}/thirdParty/javapoet/java/src"
32 | // }
33 | // }
34 | //}
35 |
36 | repositories {
37 | maven { url 'https://maven.aliyun.com/repository/public' }
38 | google()
39 | mavenCentral()
40 | }
41 |
42 | compileKotlin {
43 | kotlinOptions.jvmTarget = "1.8"
44 | }
45 | compileTestKotlin {
46 | kotlinOptions.jvmTarget = "1.8"
47 | }
48 |
49 | if (!hasProperty('StudioCompilePath')) {
50 | throw new GradleException("No StudioCompilePath value was set, please create gradle.properties file")
51 | }
52 |
53 | intellij {
54 | version '2019.3'
55 | plugins 'java'
56 | plugins 'org.jetbrains.kotlin:1.3.72-release-IJ2019.3-1' //here
57 | // plugins 'org.jetbrains.kotlin:1.3.21-release-IJ2018.2-1' //here
58 | // version '2018.2'
59 | // plugins 'org.jetbrains.kotlin:1.2.61-release-IJ2018.2-1' //here
60 | // version '2018.1'
61 | // plugins 'org.jetbrains.kotlin:1.2.60-release-IJ2018.1-1' //here
62 | // version '2017.3'
63 | // plugins 'org.jetbrains.kotlin:1.2.61-release-IJ2017.3-1' //here
64 | intellij.updateSinceUntilBuild false
65 | // intellij.localPath = project.hasProperty("StudioRunPath") ? StudioRunPath : StudioCompilePath
66 | }
67 |
68 | dependencies {
69 | compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
70 | compileOnly fileTree(dir: "$StudioCompilePath/plugins/android/lib", include: ['*.jar'])
71 | compileOnly fileTree(dir: "$StudioCompilePath/plugins/java/lib", include: ['*.jar'])
72 | compileOnly fileTree(dir: "$StudioCompilePath/lib", include: ['*.jar'])
73 |
74 | testCompile fileTree(dir: "$StudioCompilePath/plugins/android/lib", include: ['*.jar'])
75 | testCompile fileTree(dir: "$StudioCompilePath/plugins/java/lib", include: ['*.jar'])
76 | testCompile fileTree(dir: "$StudioCompilePath/lib", include: ['*.jar'])
77 | // compile "com.jetbrains.intellij.java:java-psi:192.7142.36"
78 | compileOnly "com.android.tools.build:gradle:3.6.1"
79 | // compileOnly "com.jetbrains.intellij.java:java:192.7142.36"
80 | // compile 'com.squareup:javapoet:1.11.0'
81 | // testCompile group: 'junit', name: 'junit', version: '4.12'
82 | }
83 |
84 | patchPluginXml {
85 | changeNotes """Adapte Android studio 4.0.
86 |
87 | Full Changelog History"""
88 | }
89 |
90 | //publishPlugin {
91 | // token publishToken
92 | //}
93 |
94 | //指定编译的编码
95 | tasks.withType(JavaCompile) {
96 | options.encoding = "UTF-8"
97 | }
98 |
99 | task verifySetup() {
100 | doLast {
101 | def ideaJar = "$StudioCompilePath/lib/idea.jar"
102 | if (!file(ideaJar).exists()) {
103 | throw new GradleException("$ideaJar not found, set StudioCompilePath in gradle.properties")
104 | }
105 | }
106 | }
107 |
108 | compileJava.dependsOn verifySetup
--------------------------------------------------------------------------------
/ComparingReferencesInspection/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | com.lkl.plugin.ComparingReferencesInspection
7 |
8 |
9 | demo SDK: Comparing References Inspection Sample
10 |
11 |
12 | com.intellij.modules.java
13 |
14 |
15 |
16 | Adds entries to Preferences | Editor | Inspections | Java | Probable Bugs.
18 | ]]>
19 |
20 |
21 |
23 | 2.0.0 Convert to Gradle-based plugin.
24 | 1.1.0 Refactor resources, register this inspection.
25 | 1.0.0 Release 2018.3 and earlier.
26 |
27 | ]]>
28 |
29 |
30 |
31 | IntelliJ Platform SDK
32 |
33 |
34 |
35 |
58 |
66 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/MvpAutoCode/src/main/kotlin/com/lkl/plugin/maker/FileMaker.kt:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.maker
2 |
3 | import java.text.SimpleDateFormat
4 |
5 | /**
6 | * Created by XQ Yang on 2018/6/26 13:55.
7 | * Description :
8 | */
9 | @Deprecated("使用模版方式生成更简单")
10 | val mDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
11 |
12 |
13 | /*
14 | fun make(name: String, type: String, dir: PsiDirectory, project: Project?): PsiFile? {
15 | return when (type) {
16 | "1" -> javaNoImpl(name, dir, project)
17 | else -> null
18 | }
19 | }
20 |
21 | fun javaNoImpl(createName: String, dir: PsiDirectory, project: Project?): PsiFile? {
22 | val fileName = "${getContractName(createName)}.java"
23 | val file = dir.findFile(fileName)
24 | if (file != null) {
25 | return null
26 | }
27 | val path = dir.virtualFile.path
28 | val packageName = path.substring(path.indexOf("com"), path.length).replace("/", ".")
29 |
30 | val state = ServiceManager.getService(PersistentState::class.java)
31 | val vClassName = createTypeName(state.getValue(SUPER_VIEW), packageName, createName)
32 | val pClassName = createTypeName(state.getValue(SUPER_PRESENTER), packageName, createName)
33 | val mClassName = createTypeName(state.getValue(SUPER_MODEL), packageName, createName)
34 |
35 | val viewType = TypeSpec.interfaceBuilder("View").addModifiers(Modifier.PUBLIC, Modifier.STATIC)
36 | .addSuperinterface(vClassName).build()
37 | val presenterType = TypeSpec.interfaceBuilder("Presenter").addModifiers(Modifier
38 | .PUBLIC, Modifier.STATIC)
39 | .addSuperinterface(pClassName).build()
40 | val mType = TypeSpec.interfaceBuilder("Model").addModifiers(Modifier.PUBLIC, Modifier.STATIC).addSuperinterface(mClassName).build()
41 | val contract = TypeSpec.interfaceBuilder(getContractName(createName)).addModifiers(Modifier.PUBLIC).addType(viewType).addType(presenterType)
42 | .addType(mType)
43 | .build()
44 | val javaFile = JavaFile.builder(packageName, contract).addFileComment("This class generate by mvpAutoCodePlus . Void Young - " + mDateFormat.format(Date())).build()
45 | val sb = StringBuilder()
46 | javaFile.writeTo(sb)
47 | val result = PsiFileFactory.getInstance(project).createFileFromText(fileName, JavaLanguage.INSTANCE, sb.toString(), true, false, true)
48 | dir.add(result)
49 | return result
50 | }
51 |
52 |
53 | private fun createTypeName(spValue: String?, curPackageName: String, createName: String): TypeName {
54 | if (spValue.isNullOrEmpty()) {
55 | throw IllegalArgumentException("Super Interface name is null !")
56 | }
57 | val indexOf = spValue!!.lastIndexOf(".")
58 | var spName = spValue.substring(indexOf + 1, spValue.length)
59 | var sPPackageName = spValue.substring(0, indexOf)
60 | var typeName = ""
61 | if (spName.contains("<")) {
62 | val endIndex = spName.indexOf("<")
63 | typeName = spName.substring(endIndex + 1, spName.indexOf(">"))
64 | spName = spName.substring(0, endIndex)
65 | }
66 |
67 | var pClassName: TypeName = ClassName.get(sPPackageName, spName)
68 | val typeClassNames = mutableListOf()
69 | if (typeName.isNotEmpty()) {
70 | val types = typeName.split(",")
71 | for (s in types) {
72 | typeClassNames.add(when (s) {
73 | "V" -> ClassName.get(curPackageName, "${getContractName(createName)}.View")
74 | "P" -> ClassName.get(curPackageName, "${getContractName(createName)}.Presenter")
75 | "M" -> ClassName.get(curPackageName, "${getContractName(createName)}.Model")
76 | else -> throw IllegalArgumentException("$s is not support type")
77 | })
78 | }
79 | if (typeClassNames.isNotEmpty()) {
80 | pClassName = ParameterizedTypeName.get(pClassName as ClassName, typeClassNames as List?)
81 | }
82 | }
83 | return pClassName
84 | }
85 | */
86 |
87 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/base/GetterAndSetter.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.base;
2 |
3 | import com.intellij.openapi.actionSystem.AnAction;
4 | import com.intellij.openapi.actionSystem.AnActionEvent;
5 | import com.intellij.openapi.actionSystem.PlatformDataKeys;
6 | import com.intellij.openapi.command.WriteCommandAction;
7 | import com.intellij.openapi.editor.Document;
8 | import com.intellij.openapi.editor.Editor;
9 | import com.intellij.openapi.editor.SelectionModel;
10 | import com.intellij.openapi.project.Project;
11 |
12 | /**
13 | * Created by likunlun on 2020/7/11.
14 | */
15 | public class GetterAndSetter extends AnAction {
16 | @Override
17 | public void actionPerformed(AnActionEvent e) {
18 | //获取Editor和Project对象
19 | Editor editor = e.getData(PlatformDataKeys.EDITOR);
20 | Project project = e.getData(PlatformDataKeys.PROJECT);
21 | if (editor == null||project==null)
22 | return;
23 |
24 | //获取SelectionModel和Document对象
25 | SelectionModel selectionModel = editor.getSelectionModel();
26 | Document document = editor.getDocument();
27 |
28 | //拿到选中部分字符串
29 | String selectedText = selectionModel.getSelectedText();
30 |
31 | //得到选中字符串的起始和结束位置
32 | int startOffset = selectionModel.getSelectionStart();
33 | int endOffset = selectionModel.getSelectionEnd();
34 |
35 | //得到最大插入字符串(即生成的Getter和Setter函数字符串)位置
36 | int maxOffset = document.getTextLength() - 1;
37 |
38 | //计算选中字符串所在的行号,并通过行号得到下一行的第一个字符的起始偏移量
39 | int curLineNumber = document.getLineNumber(endOffset);
40 | int nextLineStartOffset = document.getLineStartOffset(curLineNumber + 1);
41 |
42 | //计算字符串的插入位置
43 | int insertOffset = maxOffset > nextLineStartOffset ? nextLineStartOffset : maxOffset;
44 |
45 | //得到选中字符串在Java类中对应的字段的类型
46 | String type = getSelectedType(document, startOffset);
47 |
48 | //对文档进行操作部分代码,需要放入Runnable接口中实现,由IDEA在内部将其通过一个新线程执行
49 | Runnable runnable = new Runnable() {
50 | @Override
51 | public void run() {
52 | //genGetterAndSetter为生成getter和setter函数部分
53 | document.insertString(insertOffset, genGetterAndSetter(selectedText, type));
54 | }
55 | };
56 |
57 | //加入任务,由IDEA调度执行这个任务
58 | WriteCommandAction.runWriteCommandAction(project, runnable);
59 |
60 | }
61 |
62 | @Override
63 | public void update(AnActionEvent e) {
64 | Editor editor = e.getData(PlatformDataKeys.EDITOR);
65 | SelectionModel selectionModel = editor.getSelectionModel();
66 |
67 | //如果没有字符串被选中,那么无需显示该Action
68 | e.getPresentation().setVisible(editor != null && selectionModel.hasSelection());
69 | }
70 |
71 | private String getSelectedType(Document document, int startOffset) {
72 |
73 | String text = document.getText().substring(0, startOffset).trim();
74 | int startIndex = text.lastIndexOf(' ');
75 |
76 | return text.substring(startIndex + 1);
77 | }
78 |
79 | private String genGetterAndSetter(String field, String type) {
80 | if (field == null || (field = field.trim()).equals(""))
81 | return "";
82 | String upperField = field;
83 | char first = field.charAt(0);
84 | if (first <= 'z' && first >= 'a') {
85 | upperField = String.valueOf(first).toUpperCase() + field.substring(1);
86 | }
87 | String getter = "\tpublic TYPE getUpperField(){ \n\t\treturn this.FIELD;\n\t}";
88 | String setter = "\tpublic void setUpperField(TYPE FIELD){\n\t\tthis.FIELD=FIELD;\n\t}";
89 |
90 | String myGetter = getter.replaceAll("TYPE", type).replaceAll("UpperField", upperField).replaceAll("FIELD", field);
91 | String mySetter = setter.replaceAll("TYPE", type).replaceAll("UpperField", upperField).replaceAll("FIELD", field);
92 |
93 | return "\n"+myGetter + "\n" + mySetter + "\n";
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/element/FieldElement.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.element;
17 |
18 | import com.intellij.openapi.util.text.StringUtil;
19 |
20 | /**
21 | * This is a field element containing information about the field.
22 | *
23 | * @see ElementFactory
24 | */
25 | public class FieldElement extends AbstractElement implements Element {
26 |
27 | private boolean isConstant;
28 | private boolean isEnum;
29 | private boolean isRecordComponent;
30 |
31 | private boolean isModifierTransient;
32 | private boolean isModifierVolatile;
33 | private String accessor;
34 |
35 | @Override
36 | public String getAccessor() {
37 | return accessor;
38 | }
39 |
40 | /**
41 | * Is the field a constant type?
42 | */
43 | public boolean isConstant() {
44 | return isConstant;
45 | }
46 |
47 | /**
48 | * Does the field have a transient modifier?
49 | */
50 | public boolean isModifierTransient() {
51 | return isModifierTransient;
52 | }
53 |
54 | /**
55 | * Does the field have a volatile modifier?
56 | */
57 | public boolean isModifierVolatile() {
58 | return isModifierVolatile;
59 | }
60 |
61 | /**
62 | * Is the field an enum type (JDK1.5)?
63 | */
64 | public boolean isEnum() {
65 | return isEnum;
66 | }
67 |
68 | /**
69 | * Is the field a record component (JDK14)?
70 | */
71 | public boolean isRecordComponent() {
72 | return isRecordComponent;
73 | }
74 |
75 | public void setRecordComponent(boolean recordComponent) {
76 | isRecordComponent = recordComponent;
77 | }
78 |
79 | void setConstant(boolean constant) {
80 | isConstant = constant;
81 | }
82 |
83 | void setModifierTransient(boolean modifierTransient) {
84 | isModifierTransient = modifierTransient;
85 | }
86 |
87 | void setModifierVolatile(boolean modifierVolatile) {
88 | this.isModifierVolatile = modifierVolatile;
89 | }
90 |
91 | public void setEnum(boolean anEnum) {
92 | isEnum = anEnum;
93 | }
94 |
95 | /**
96 | * Performs a regular expression matching the fieldname.
97 | *
98 | * @param regexp regular expression.
99 | * @return true if the fieldname matches the regular expression.
100 | * @throws IllegalArgumentException is throw if the given input is invalid (an empty String) or a pattern matching error.
101 | */
102 | public boolean matchName(String regexp) throws IllegalArgumentException {
103 | if (StringUtil.isEmpty(regexp)) {
104 | throw new IllegalArgumentException(
105 | "Can't perform regular expression since the given input is empty. Check the Method body velocity code: regexp='" + regexp + "'");
106 | }
107 |
108 | return name.matches(regexp);
109 | }
110 |
111 | public String toString() {
112 | return super.toString() + " ::: FieldElement{" +
113 | "isConstant=" + isConstant +
114 | ", isEnum=" + isEnum +
115 | ", isModifierTransient=" + isModifierTransient +
116 | ", isModifierVolatile=" + isModifierVolatile +
117 | "}";
118 | }
119 |
120 | public void setAccessor(String accessor) {
121 | this.accessor = accessor;
122 | }
123 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/template/toString/ToStringTemplatesManager.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 | package com.lkl.plugin.tostring.template.toString;
3 |
4 | import com.intellij.openapi.components.ServiceManager;
5 | import com.intellij.openapi.components.State;
6 | import com.intellij.openapi.components.Storage;
7 | import com.lkl.plugin.tostring.exception.TemplateResourceException;
8 | import com.lkl.plugin.tostring.template.TemplateResource;
9 | import com.lkl.plugin.tostring.template.TemplatesManager;
10 | import org.jetbrains.annotations.NotNull;
11 |
12 |
13 | import java.io.IOException;
14 | import java.util.Arrays;
15 | import java.util.List;
16 |
17 | @State(name = "ToStringTemplates", storages = @Storage("toStringTemplates.xml"))
18 | public final class ToStringTemplatesManager extends TemplatesManager {
19 | private static final String DEFAULT_CONCAT = "DefaultConcatMember.vm";
20 | private static final String DEFAULT_CONCAT_GROOVY = "/com/lkl/plugin/tostring/template/toString/DefaultConcatMemberGroovy.vm";
21 | private static final String DEFAULT_CONCAT_SUPER = "/com/lkl/plugin/tostring/template/toString/DefaultConcatMemberSuper.vm";
22 | private static final String DEFAULT_CONCAT_SUPER_GROOVY = "/com/lkl/plugin/tostring/template/toString/DefaultConcatMemberSuperGroovy.vm";
23 | private static final String DEFAULT_BUFFER = "/com/lkl/plugin/tostring/template/toString/DefaultBuffer.vm";
24 | private static final String DEFAULT_BUILDER = "/com/lkl/plugin/tostring/template/toString/DefaultBuilder.vm";
25 | private static final String DEFAULT_TOSTRINGBUILDER = "/com/lkl/plugin/tostring/template/toString/DefaultToStringBuilder.vm";
26 | private static final String DEFAULT_TOSTRINGBUILDER3 = "/com/lkl/plugin/tostring/template/toString/DefaultToStringBuilder3.vm";
27 | private static final String DEFAULT_GUAVA = "/com/lkl/plugin/tostring/template/toString/DefaultGuava.vm";
28 | private static final String DEFAULT_GUAVA_18 = "/com/lkl/plugin/tostring/template/toString/DefaultGuava18.vm";
29 | private static final String DEFAULT_STRING_JOINER = "/com/lkl/plugin/tostring/template/toString/StringJoiner.vm";
30 |
31 | public static TemplatesManager getInstance() {
32 | return ServiceManager.getService(ToStringTemplatesManager.class);
33 | }
34 |
35 | @Override
36 | public @NotNull List getDefaultTemplates() {
37 | try {
38 | return Arrays.asList(new TemplateResource("String concat (+)", readFile(DEFAULT_CONCAT), true),
39 | new TemplateResource("String concat (+) and super.toString()", readFile(DEFAULT_CONCAT_SUPER), true),
40 | new TemplateResource("StringBuffer", readFile(DEFAULT_BUFFER), true),
41 | new TemplateResource("StringBuilder (JDK 1.5)", readFile(DEFAULT_BUILDER), true),
42 | new TemplateResource("ToStringBuilder (Apache commons-lang)", readFile(DEFAULT_TOSTRINGBUILDER), true, "org.apache.commons.lang.builder.ToStringBuilder"),
43 | new TemplateResource("ToStringBuilder (Apache commons-lang 3)", readFile(DEFAULT_TOSTRINGBUILDER3), true, "org.apache.commons.lang3.builder.ToStringBuilder"),
44 | new TemplateResource("Objects.toStringHelper (Guava)", readFile(DEFAULT_GUAVA), true, "com.google.common.base.Objects"),
45 | new TemplateResource("MoreObjects.toStringHelper (Guava 18+)", readFile(DEFAULT_GUAVA_18), true, "com.google.common.base.MoreObjects"),
46 | new TemplateResource("StringJoiner (JDK 1.8)", readFile(DEFAULT_STRING_JOINER), true),
47 | new TemplateResource("Groovy: String concat (+)", readFile(DEFAULT_CONCAT_GROOVY), true),
48 | new TemplateResource("Groovy: String concat (+) and super.toString()", readFile(DEFAULT_CONCAT_SUPER_GROOVY), true));
49 | }
50 | catch (IOException e) {
51 | throw new TemplateResourceException("Error loading default templates", e);
52 | }
53 | }
54 |
55 | protected static String readFile(String resource) throws IOException {
56 | return readFile(resource, ToStringTemplatesManager.class);
57 | }
58 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/element/GenerationHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2000-2015 JetBrains s.r.o.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.element;
17 |
18 | import com.intellij.openapi.project.Project;
19 | import com.intellij.openapi.util.text.StringUtil;
20 | import com.intellij.psi.JavaPsiFacade;
21 | import com.intellij.psi.PsiClass;
22 | import com.intellij.psi.PsiFile;
23 | import com.intellij.psi.PsiJavaFile;
24 | import com.intellij.psi.codeStyle.JavaCodeStyleManager;
25 | import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
26 | import com.intellij.psi.codeStyle.VariableKind;
27 | import com.intellij.psi.search.GlobalSearchScope;
28 |
29 | import java.util.List;
30 |
31 | public class GenerationHelper {
32 |
33 | //used in generate equals/hashCode
34 | @SuppressWarnings("unused")
35 | public static String getUniqueLocalVarName(String base, List extends Element> elements, JavaCodeStyleSettings settings) {
36 | base = settings.LOCAL_VARIABLE_NAME_PREFIX + base;
37 | String id = base;
38 | int index = 0;
39 | while (true) {
40 | if (index > 0) {
41 | id = base + index;
42 | }
43 | index++;
44 | boolean anyEqual = false;
45 | for (Element equalsField : elements) {
46 | if (id.equals(equalsField.getName())) {
47 | anyEqual = true;
48 | break;
49 | }
50 | }
51 | if (!anyEqual) break;
52 | }
53 |
54 |
55 | return id;
56 | }
57 |
58 | /**
59 | * To be used from generate templates
60 | */
61 | @SuppressWarnings("unused")
62 | public static String getClassNameWithOuters(ClassElement classElement, Project project) {
63 | String qualifiedName = classElement.getQualifiedName();
64 | PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(qualifiedName, GlobalSearchScope.projectScope(project));
65 | if (aClass != null) {
66 | PsiFile containingFile = aClass.getContainingFile();
67 | if (containingFile instanceof PsiJavaFile) {
68 | String packageName = ((PsiJavaFile)containingFile).getPackageName();
69 | if (qualifiedName.startsWith(packageName)) {
70 | if (packageName.isEmpty()) return qualifiedName;
71 | return qualifiedName.substring(packageName.length() + 1);
72 | }
73 | }
74 | }
75 | return classElement.getName();
76 | }
77 |
78 | public static String getParamName(FieldElement fieldElement, Project project) {
79 | JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
80 | return codeStyleManager.propertyNameToVariableName(getPropertyName(fieldElement, project), VariableKind.PARAMETER);
81 | }
82 |
83 | public static String getPropertyName(FieldElement fieldElement, Project project) {
84 | final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
85 | final VariableKind variableKind = fieldElement.isModifierStatic() ? VariableKind.STATIC_FIELD : VariableKind.FIELD;
86 | final String propertyName = codeStyleManager.variableNameToPropertyName(fieldElement.getName(), variableKind);
87 | if (!fieldElement.isModifierStatic() && fieldElement.isBoolean()) {
88 | if (propertyName.startsWith("is") &&
89 | propertyName.length() > "is".length() &&
90 | Character.isUpperCase(propertyName.charAt("is".length()))) {
91 | return StringUtil.decapitalize(propertyName.substring("is".length()));
92 | }
93 | }
94 | return propertyName;
95 | }
96 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/element/MethodElement.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2013 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.element;
17 |
18 | import com.intellij.openapi.util.text.StringUtil;
19 |
20 | /**
21 | * This is a method element containing information about the method.
22 | *
23 | * @see ElementFactory
24 | */
25 | @SuppressWarnings({"UnusedDeclaration"})
26 | public class MethodElement extends AbstractElement implements Element {
27 |
28 | private String methodName;
29 | private String fieldName;
30 | private boolean modifierAbstract;
31 | private boolean modifierSynchronized;
32 | private boolean returnTypeVoid;
33 | private boolean getter;
34 | private boolean deprecated;
35 |
36 | public String getMethodName() {
37 | return methodName;
38 | }
39 |
40 | public void setMethodName(String methodName) {
41 | this.methodName = methodName;
42 | }
43 |
44 | public String getFieldName() {
45 | return fieldName;
46 | }
47 |
48 | public void setFieldName(String fieldName) {
49 | this.fieldName = fieldName;
50 | }
51 |
52 | @Override
53 | public String getAccessor() {
54 | return methodName + "()";
55 | }
56 |
57 | public boolean isModifierAbstract() {
58 | return modifierAbstract;
59 | }
60 |
61 | public void setModifierAbstract(boolean modifierAbstract) {
62 | this.modifierAbstract = modifierAbstract;
63 | }
64 |
65 | /**
66 | * Exists for compatibility with old templates
67 | */
68 | public boolean isModifierSynchronzied() {
69 | return isModifierSynchronized();
70 | }
71 |
72 | public boolean isModifierSynchronized() {
73 | return modifierSynchronized;
74 | }
75 |
76 | public void setModifierSynchronized(boolean modifierSynchronized) {
77 | this.modifierSynchronized = modifierSynchronized;
78 | }
79 |
80 | public boolean isReturnTypeVoid() {
81 | return returnTypeVoid;
82 | }
83 |
84 | public void setReturnTypeVoid(boolean returnTypeVoid) {
85 | this.returnTypeVoid = returnTypeVoid;
86 | }
87 |
88 | public boolean isGetter() {
89 | return getter;
90 | }
91 |
92 | public void setGetter(boolean getter) {
93 | this.getter = getter;
94 | }
95 |
96 | public boolean isDeprecated() {
97 | return deprecated;
98 | }
99 |
100 | public void setDeprecated(boolean deprecated) {
101 | this.deprecated = deprecated;
102 | }
103 |
104 | /**
105 | * Performs a regular expression matching the methodname.
106 | *
107 | * @param regexp regular expression.
108 | * @return true if the methodname matches the regular expression.
109 | * @throws IllegalArgumentException is throw if the given input is invalid (an empty String) or a pattern matching error.
110 | */
111 | public boolean matchName(String regexp) throws IllegalArgumentException {
112 | if (StringUtil.isEmpty(regexp)) {
113 | throw new IllegalArgumentException("Can't perform regular expression since the given input is empty. Check the Method body velocity code: regexp='" + regexp + "'");
114 | }
115 |
116 | return methodName.matches(regexp);
117 | }
118 |
119 | public String toString() {
120 | return super.toString() + " ::: MethodElement{" +
121 | "fieldName='" + fieldName + "'" +
122 | ", methodName='" + methodName + "'" +
123 | ", modifierAbstract=" + modifierAbstract +
124 | ", modifierSynchronized=" + modifierSynchronized +
125 | ", returnTypeVoid=" + returnTypeVoid +
126 | ", getter=" + getter +
127 | ", deprecated=" + deprecated +
128 | "}";
129 | }
130 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/configurable/ExeOverwriteConfirmDialog.form:
--------------------------------------------------------------------------------
1 |
2 |
81 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/element/ElementUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2001-2012 the original author or authors.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.lkl.plugin.tostring.element;
17 |
18 | import com.intellij.psi.PsiField;
19 | import com.intellij.psi.PsiMember;
20 | import com.intellij.psi.PsiMethod;
21 |
22 | import java.util.ArrayList;
23 | import java.util.Collection;
24 | import java.util.List;
25 |
26 | /**
27 | * Element utilities.
28 | */
29 | public final class ElementUtils {
30 |
31 | private ElementUtils() {}
32 |
33 | /**
34 | * Gets the list of members to be put in the VelocityContext.
35 | *
36 | * @param members a list of {@link PsiMember} objects.
37 | * @param selectedNotNullMembers
38 | * @param useAccessors
39 | * @return a filtered list of only the fields as {@link FieldElement} objects.
40 | */
41 | public static List getOnlyAsFieldElements(Collection extends PsiMember> members,
42 | Collection extends PsiMember> selectedNotNullMembers,
43 | boolean useAccessors) {
44 | List fieldElementList = new ArrayList<>();
45 |
46 | for (PsiMember member : members) {
47 | if (member instanceof PsiField) {
48 | PsiField field = (PsiField) member;
49 | FieldElement fe = ElementFactory.newFieldElement(field, useAccessors);
50 | if (selectedNotNullMembers.contains(member)) {
51 | fe.setNotNull(true);
52 | }
53 | fieldElementList.add(fe);
54 | }
55 | }
56 |
57 | return fieldElementList;
58 | }
59 |
60 | /**
61 | * Gets the list of members to be put in the VelocityContext.
62 | *
63 | * @param members a list of {@link PsiMember} objects.
64 | * @return a filtered list of only the methods as a {@link MethodElement} objects.
65 | */
66 | public static List getOnlyAsMethodElements(Collection extends PsiMember> members) {
67 | List methodElementList = new ArrayList<>();
68 |
69 | for (PsiMember member : members) {
70 | if (member instanceof PsiMethod) {
71 | PsiMethod method = (PsiMethod) member;
72 | MethodElement me = ElementFactory.newMethodElement(method);
73 | methodElementList.add(me);
74 | }
75 | }
76 |
77 | return methodElementList;
78 | }
79 |
80 | /**
81 | * Gets the list of members to be put in the VelocityContext.
82 | *
83 | * @param members a list of {@link PsiMember} objects.
84 | * @param selectedNotNullMembers a list of @NotNull objects
85 | * @param useAccessors
86 | * @return a filtered list of only the methods as a {@link FieldElement} or {@link MethodElement} objects.
87 | */
88 | public static List getOnlyAsFieldAndMethodElements(Collection extends PsiMember> members,
89 | Collection extends PsiMember> selectedNotNullMembers,
90 | boolean useAccessors) {
91 | List elementList = new ArrayList<>();
92 |
93 | for (PsiMember member : members) {
94 | AbstractElement element = null;
95 | if (member instanceof PsiField) {
96 | element = ElementFactory.newFieldElement((PsiField) member, useAccessors);
97 | } else if (member instanceof PsiMethod) {
98 | element = ElementFactory.newMethodElement((PsiMethod) member);
99 | }
100 |
101 | if (element != null) {
102 | if (selectedNotNullMembers.contains(member)) {
103 | element.setNotNull(true);
104 | }
105 | elementList.add(element);
106 | }
107 | }
108 | return elementList;
109 | }
110 | }
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | com.lkl.plugin.IdeaPluginStudy
3 | IdeaPluginStudy
4 | 1.0
5 | YourCompany
6 |
7 |
9 | most HTML tags may be used
10 | ]]>
11 |
12 |
14 | most HTML tags may be used
15 | ]]>
16 |
17 |
18 |
19 |
20 |
21 |
23 |
26 |
27 |
28 |
29 |
34 |
37 |
38 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
63 |
64 |
65 |
66 |
68 |
69 |
71 |
72 |
73 |
74 |
75 |
79 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/docs/advanced/persistStateComponent.md:
--------------------------------------------------------------------------------
1 | # IntelliJ Plugin Development introduction: PersistStateComponent
2 |
3 | * [为IntelliJ插件保存值](#为intellij插件保存值)
4 | * [使类实现PersistentStateComponent](#使类实现persistentstatecomponent)
5 | * [@State注解–指定要保存的存储位置](#指定要保存的存储位置)
6 | * [在plugin.xml中声明PersistentStateComponent](#声明PersistentStateComponent)
7 | * [从其他模块使用PersistentStateComponent](#从其他模块使用persistentstatecomponent)
8 |
9 | ## 为IntelliJ插件保存值
10 |
11 | 如果您的插件想要保留一些配置值,并且希望将这些值保存在存储器中,则可以在IntelliJ IDEA插件开发中使用`PersistentStateComponent`。
12 |
13 | * [Persisting State of Components](https://www.jetbrains.org/intellij/sdk/docs/basics/persisting_state_of_components.html)
14 |
15 | ## 使类实现PersistentStateComponent
16 |
17 | 创建新的Java类`SingleFileExecutionConfig`实现`PersistentStateComponent`。
18 |
19 | 该类实现了`PersistentStateComponent`。因此,状态类型T与创建的类相同。
20 |
21 | 要实现此接口`PersistentStateComponent`,我们需要重写
22 |
23 | * **getState()** 每次保存设置时调用。如果从`getState()`返回的状态不同于默认构造函数获得的默认状态,则返回的状态将以XML序列化并存储。
24 | * **loadState(T)** 在创建组件时以及在外部更改具有持久状态的XML文件之后调用。
25 |
26 | 并且实现`getInstance`方法。
27 |
28 | 对于这三种方法的实现,您无需记住上述行为。 只需实现如下模板即可:
29 | ```java
30 | /**
31 | * PersistentStateComponent keeps project config values.
32 | */
33 | @State(
34 | name="SingleFileExecutionConfig",
35 | storages = {
36 | @Storage("SingleFileExecutionConfig.xml")}
37 | )
38 | public class SingleFileExecutionConfig implements PersistentStateComponent {
39 |
40 | @Nullable
41 | @Override
42 | public SingleFileExecutionConfig getState() {
43 | return this;
44 | }
45 |
46 | @Override
47 | public void loadState(SingleFileExecutionConfig singleFileExecutionConfig) {
48 | XmlSerializerUtil.copyBean(singleFileExecutionConfig, this);
49 | }
50 |
51 | @Nullable
52 | public static SingleFileExecutionConfig getInstance(Project project) {
53 | return ServiceManager.getService(project, SingleFileExecutionConfig.class);
54 | }
55 | }
56 | ```
57 |
58 | > 请注意,当`PersistentStateComponent`为项目级别时,对于`getInstance`中的`getService`方法,`project`变量是必需的。如果您的Service是应用程序级别的,则不需要`project`实例。
59 |
60 | * [Plugin Services](https://www.jetbrains.org/intellij/sdk/docs/basics/plugin_structure/plugin_services.html)
61 |
62 | ## @State注解–指定要保存的存储位置
63 |
64 | 您可能会注意到,@State注解写在顶部。这是用来指定将存储持久值的位置。
65 |
66 | For the fields:
67 | * name (required) – specifies the name of the state.
68 | * storages – specify the storage locations
69 |
70 | Example:
71 | @Storage("yourName.xml") If component is project-level
72 | @Storage(StoragePathMacros.WORKSPACE_FILE) for values stored in the workspace file.
73 |
74 | 有关更多详细信息,请参见官方文档的[“定义存储位置”](https://www.jetbrains.org/intellij/sdk/docs/basics/persisting_state_of_components.html)
75 |
76 | 之后,您只需声明将要保存的变量,以及这些变量的Getter和Setter。 例如,要声明一个String变量executableName,请将以下代码添加到此类。
77 | ```java
78 | String executableName;
79 |
80 | public String getExecutableName() {
81 | return executableName;
82 | }
83 |
84 | public void setExecutableName(String executableName) {
85 | this.executableName = executableName;
86 | }
87 | ```
88 |
89 | ## 在plugin.xml中声明PersistentStateComponent
90 |
91 | 要使用此PersistentStateComponent,需要在plugin.xml中进行声明
92 | ```xml
93 |
94 |
95 | ...
96 |
99 |
100 | ```
101 |
102 | ## 从其他模块使用PersistentStateComponent
103 |
104 | 可以通过调用getInstance方法获得实例。例如:
105 | ```java
106 | private final SingleFileExecutionConfig mConfig;
107 |
108 | @SuppressWarnings("FieldCanBeLocal")
109 | private final Project mProject;
110 |
111 | public SingleFileExecutionConfigurable(@NotNull Project project) {
112 | mProject = project;
113 | mConfig = SingleFileExecutionConfig.getInstance(project);
114 | }
115 | ```
116 | 要更新值,您可以直接更新此实例的字段变量`(mConfig)`。不需要显式的`“save”`方法调用!下次获取值时,该值将自动保存。
117 |
118 | > **注意**:`public SingleFileExecutionConfigurable(@NotNull Project project)` 接收project作为参数时,在 `plugin.xml` 中一定要声明为 `projectConfigurable`
119 |
120 | 下面的代码是变量更新部分的示例。 当用户在“设置”对话框中更改配置时,将调用此`apply()`方法。
121 | ```java
122 | public void apply() {
123 | mConfig.setExecutableName(exeNameTextField.getText());
124 | mConfig.notShowOverwriteConfirmDialog = notShowDialogCheckBox.isSelected();
125 | }
126 | ```
127 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/config/CodeTemplate.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.config;
2 |
3 | import com.intellij.openapi.util.io.FileUtil;
4 | import com.intellij.util.xmlb.annotations.AbstractCollection;
5 | import org.apache.commons.lang.builder.EqualsBuilder;
6 | import org.apache.commons.lang.builder.HashCodeBuilder;
7 | import org.jetbrains.java.generate.config.DuplicationPolicy;
8 | import org.jetbrains.java.generate.config.InsertWhere;
9 |
10 | import javax.xml.bind.annotation.*;
11 | import java.io.IOException;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 | import java.util.UUID;
15 |
16 | @XmlRootElement(name = "codeTemplate")
17 | @XmlAccessorType(XmlAccessType.FIELD)
18 | public class CodeTemplate {
19 | @XmlAttribute
20 | public static final String VERSION = "1.3";
21 |
22 | private UUID id;
23 | public String name = "Untitled";
24 | public String fileNamePattern = ".*\\.java$";
25 | public String type = "body";
26 | public boolean enabled = true;
27 | public String template = DEFAULT_TEMPLATE;
28 | public String fileEncoding = DEFAULT_ENCODING;
29 | @XmlElements({
30 | @XmlElement(name="memberSelection", type=MemberSelectionConfig.class),
31 | @XmlElement(name="classSelection", type=ClassSelectionConfig.class)
32 | })
33 | @XmlElementWrapper
34 | @AbstractCollection(elementTypes = {MemberSelectionConfig.class, ClassSelectionConfig.class})
35 | public List pipeline = new ArrayList<>();
36 |
37 | public InsertWhere insertNewMethodOption = InsertWhere.AT_CARET;
38 | public DuplicationPolicy whenDuplicatesOption = DuplicationPolicy.ASK;
39 | public boolean jumpToMethod = true; // jump cursor to toString method
40 | public String classNameVm = "${class0.qualifiedName}Test";
41 | public boolean alwaysPromptForPackage = false;
42 |
43 | public CodeTemplate(UUID id) {
44 | this.id = id;
45 | }
46 | public CodeTemplate(String id) {
47 | this.id = UUID.fromString(id);
48 | }
49 |
50 | public CodeTemplate() {
51 | this(UUID.randomUUID());
52 | }
53 |
54 | public void regenerateId() {
55 | this.id = UUID.randomUUID();
56 | }
57 |
58 | public String getId() {
59 | return this.id.toString();
60 | }
61 |
62 | public boolean isValid() {
63 | return true;
64 | }
65 |
66 | public static final String DEFAULT_ENCODING = "UTF-8";
67 |
68 | private static final String DEFAULT_TEMPLATE;
69 |
70 | static {
71 | String default_template;
72 | try {
73 | default_template = FileUtil.loadTextAndClose(CodeTemplate.class.getResourceAsStream("/template/default.vm"));
74 | } catch (IOException e) {
75 | default_template = "";
76 | e.printStackTrace();
77 | }
78 | DEFAULT_TEMPLATE = default_template;
79 | }
80 |
81 | @Override public boolean equals(Object o) {
82 | if (this == o)
83 | return true;
84 |
85 | if (o == null || getClass() != o.getClass())
86 | return false;
87 |
88 | CodeTemplate template1 = (CodeTemplate)o;
89 |
90 | return new EqualsBuilder()
91 | .append(enabled, template1.enabled)
92 | .append(jumpToMethod, template1.jumpToMethod)
93 | .append(alwaysPromptForPackage, template1.alwaysPromptForPackage)
94 | .append(id, template1.id)
95 | .append(name, template1.name)
96 | .append(fileNamePattern, template1.fileNamePattern)
97 | .append(type, template1.type)
98 | .append(template, template1.template)
99 | .append(fileEncoding, template1.fileEncoding)
100 | .append(pipeline, template1.pipeline)
101 | .append(insertNewMethodOption, template1.insertNewMethodOption)
102 | .append(whenDuplicatesOption, template1.whenDuplicatesOption)
103 | .append(classNameVm, template1.classNameVm)
104 | .isEquals();
105 | }
106 |
107 | @Override public int hashCode() {
108 | return new HashCodeBuilder(17, 37)
109 | .append(id)
110 | .append(name)
111 | .append(fileNamePattern)
112 | .append(type)
113 | .append(enabled)
114 | .append(template)
115 | .append(fileEncoding)
116 | .append(pipeline)
117 | .append(insertNewMethodOption)
118 | .append(whenDuplicatesOption)
119 | .append(jumpToMethod)
120 | .append(classNameVm)
121 | .append(alwaysPromptForPackage)
122 | .toHashCode();
123 | }
124 |
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/resources/template/default.vm:
--------------------------------------------------------------------------------
1 | ## Tutorial for writing your templates
2 | ##
3 | ## 1. First you need to know basic syntax of velocity[1].
4 | ## 2. Then it is necessary to understand the variable that CodeGenerator provides
5 | ## and its inner structure for retrieving the information you need for generating code.
6 | ## 3. Learn to use the utils provided so that you can ask for further information
7 | ## or reduce your workload.
8 | ##
9 | ## Variables Provided (Class Mode)
10 | ## -------------------------------
11 | ## Class mode means you want to create new classes(file).
12 | ##
13 | ## - ClassName: String The name spcified by `Target Class Name`
14 | ## - PackageName: String The package name specified by `Target Class Name`
15 | ## - class0: ClassEntry The class that the action is triggered upon
16 | ## - raw: PsiClass
17 | ## - String packageName
18 | ## - importList: List
19 | ## - fields: List
20 | ## - allFields: List
21 | ## - methods: List
22 | ## - allMethods: List
23 | ## - innerClasses: List
24 | ## - allInnerClasses: List
25 | ## - typeParamList: List
26 | ## - name: String
27 | ## - superName: String
28 | ## - superQualifiedName: String
29 | ## - qualifiedName: String
30 | ## - typeParams: int
31 | ## - hasSuper: boolean
32 | ## - deprecated: boolean
33 | ## - enum: boolean
34 | ## - exception: boolean
35 | ## - abstract: boolean
36 | ## - implementNames: String[]
37 | ## - isImplements(String): bool
38 | ## - isExtends(String): bool
39 | ## - matchName(String): bool
40 | ##
41 | ## - class1: ClassEntry The first selected class, where `1` is the postfix
42 | ## you specify in pipeline
43 | ## ...
44 | ##
45 | ## - MemberEntry (FieldEntry/MethodEntry common properties)
46 | ## - raw: PsiField(for field), PsiMethod(for method)
47 | ## - name: String
48 | ## - accessor: String
49 | ## - array: boolean
50 | ## - nestedArray: boolean
51 | ## - collection: boolean
52 | ## - map: boolean
53 | ## - primitive: boolean
54 | ## - string: boolean
55 | ## - primitiveArray: boolean
56 | ## - objectArray: boolean
57 | ## - numeric: boolean
58 | ## - object: boolean
59 | ## - date: boolean
60 | ## - set: boolean
61 | ## - list: boolean
62 | ## - stringArray: boolean
63 | ## - calendar: boolean
64 | ## - typeName: String
65 | ## - typeQualifiedName: String
66 | ## - type: String
67 | ## - boolean: boolean
68 | ## - long: boolean
69 | ## - float: boolean
70 | ## - double: boolean
71 | ## - void: boolean
72 | ## - notNull: boolean
73 | ## - char: boolean
74 | ## - byte: boolean
75 | ## - short: boolean
76 | ## - modifierStatic: boolean
77 | ## - modifierPublic: boolean
78 | ## - modifierProtected: boolean
79 | ## - modifierPackageLocal: boolean
80 | ## - modifierPrivate: boolean
81 | ## - modifierFinal: boolean
82 | ##
83 | ## - FieldEntry
84 | ## - constant: boolean
85 | ## - modifierTransient: boolean
86 | ## - modifierVolatile: boolean
87 | ## - enum: boolean
88 | ## - matchName(String): bool
89 | ##
90 | ## - MethodEntry
91 | ## - methodName: String
92 | ## - fieldName: String
93 | ## - modifierAbstract: boolean
94 | ## - modifierSynchronzied: boolean
95 | ## - modifierSynchronized: boolean
96 | ## - returnTypeVoid: boolean
97 | ## - getter: boolean
98 | ## - deprecated: boolean
99 | ## - matchName(String): bool
100 | ##
101 | ## Variables for Body Mode
102 | ## -----------------------
103 | ## - class0: ClassEntry The current class
104 | ## - fields: List All selected fields
105 | ## - methods: List All selected methods
106 | ## - members: List selected fields+methods
107 | ## - parentMethod: MethodEntry The nearest method that surround the current cursor
108 | ##
109 | ## Utilities
110 | ## ---------
111 | ## - settings: CodeStyleSettings settings of code style
112 | ## - project: Project The project instance, normally used by Psi related utilities
113 | ## - helper: GenerationHelper
114 | ## - StringUtil: Class
115 | ## - NameUtil: Class
116 | ## - PsiShortNamesCache: Class utility to search classes
117 | ## - PsiJavaPsiFacade: Class Java specific utility to search classes
118 | ## - GlobalSearchScope: Class class to create search scopes, used by above utilities
119 | ## - EntryFactory: Class EntryFactory.of(...) to turn PsiXXX to XXXEntry.
120 | ##
121 | ## Other feature
122 | ## -------------
123 | ## - Auto import. If the generated code contains full qualified name, Code Generator will try to
124 | ## import the packages automatically and shorten the name.
125 | ## For example `java.util.List<>` -> `List<>`
126 | ##
127 | ## References
128 | ## ----------
129 | ## - Velocity syntax: http://velocity.apache.org/engine/1.7/user-guide.html
130 |
131 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/tostring/view/TemplatesPanel.java:
--------------------------------------------------------------------------------
1 | // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 |
3 | /*
4 | * @author max
5 | */
6 | package com.lkl.plugin.tostring.view;
7 |
8 | import com.intellij.java.JavaBundle;
9 | import com.intellij.openapi.options.ConfigurationException;
10 | import com.intellij.openapi.options.UnnamedConfigurable;
11 | import com.intellij.openapi.project.Project;
12 | import com.intellij.openapi.ui.NamedItemsListEditor;
13 | import com.intellij.openapi.ui.Namer;
14 | import com.intellij.openapi.util.Cloner;
15 | import com.intellij.openapi.util.Comparing;
16 | import com.intellij.openapi.util.Factory;
17 | import com.lkl.plugin.tostring.template.TemplateResource;
18 | import com.lkl.plugin.tostring.template.TemplatesManager;
19 | import com.lkl.plugin.tostring.template.toString.ToStringTemplatesManager;
20 | import gnu.trove.Equality;
21 | import org.jetbrains.annotations.Nls;
22 | import org.jetbrains.annotations.NonNls;
23 | import org.jetbrains.annotations.Nullable;
24 |
25 | import java.util.ArrayList;
26 | import java.util.Collections;
27 | import java.util.Objects;
28 |
29 | public class TemplatesPanel extends NamedItemsListEditor {
30 | private static final Namer NAMER = new Namer() {
31 | @Override
32 | public String getName(TemplateResource templateResource) {
33 | return templateResource.getFileName();
34 | }
35 |
36 | @Override
37 | public boolean canRename(TemplateResource item) {
38 | return !item.isDefault();
39 | }
40 |
41 | @Override
42 | public void setName(TemplateResource templateResource, String name) {
43 | templateResource.setFileName(name);
44 | }
45 | };
46 |
47 | private static final Factory FACTORY = () -> new TemplateResource();
48 |
49 | private static final Cloner CLONER = new Cloner() {
50 | @Override
51 | public TemplateResource cloneOf(TemplateResource templateResource) {
52 | if (templateResource.isDefault()) return templateResource;
53 | return copyOf(templateResource);
54 | }
55 |
56 | @Override
57 | public TemplateResource copyOf(TemplateResource templateResource) {
58 | TemplateResource result = new TemplateResource();
59 | result.setFileName(templateResource.getFileName());
60 | result.setTemplate(templateResource.getTemplate());
61 | return result;
62 | }
63 | };
64 |
65 | private static final Equality COMPARER =
66 | (o1, o2) -> Objects.equals(o1.getTemplate(), o2.getTemplate()) && Objects.equals(o1.getFileName(), o2.getFileName());
67 | private final Project myProject;
68 | private final TemplatesManager myTemplatesManager;
69 | private String myHint;
70 |
71 | public TemplatesPanel(Project project) {
72 | this(project, ToStringTemplatesManager.getInstance());
73 | }
74 |
75 | public TemplatesPanel(Project project, TemplatesManager templatesManager) {
76 | super(NAMER, FACTORY, CLONER, COMPARER,
77 | new ArrayList<>(templatesManager.getAllTemplates()));
78 |
79 | //ServiceManager.getService(project, MasterDetailsStateService.class).register("ToStringTemplates.UI", this);
80 | myProject = project;
81 | myTemplatesManager = templatesManager;
82 | }
83 |
84 | public void setHint(String hint) {
85 | myHint = hint;
86 | }
87 |
88 | @Override
89 | @Nls
90 | public String getDisplayName() {
91 | return JavaBundle.message("configurable.TemplatesPanel.display.name");
92 | }
93 |
94 | @Override
95 | protected String subjDisplayName() {
96 | return "template";
97 | }
98 |
99 | @Override
100 | @Nullable
101 | @NonNls
102 | public String getHelpTopic() {
103 | return "Templates_Dialog";
104 | }
105 |
106 | @Override
107 | public boolean isModified() {
108 | return super.isModified() || !Comparing.equal(myTemplatesManager.getDefaultTemplate(), getSelectedItem());
109 | }
110 |
111 | @Override
112 | protected boolean canDelete(TemplateResource item) {
113 | return !item.isDefault();
114 | }
115 |
116 | @Override
117 | protected UnnamedConfigurable createConfigurable(TemplateResource item) {
118 | final GenerateTemplateConfigurable configurable =
119 | new GenerateTemplateConfigurable(item, Collections.emptyMap(), myProject, onMultipleFields());
120 | configurable.setHint(myHint);
121 | return configurable;
122 | }
123 |
124 | protected boolean onMultipleFields() {
125 | return true;
126 | }
127 |
128 | @Override
129 | public void apply() throws ConfigurationException {
130 | super.apply();
131 | myTemplatesManager.setTemplates(getItems());
132 | final TemplateResource selection = getSelectedItem();
133 | if (selection != null) {
134 | myTemplatesManager.setDefaultTemplate(selection);
135 | }
136 | }
137 | }
--------------------------------------------------------------------------------
/docs/base/kotlinPlugin.md:
--------------------------------------------------------------------------------
1 | # Kotlin for Plugin Developers
2 |
3 | * [Why Kotlin?](#WhyKotlin?)
4 | * [Adding Kotlin Support](#AddingKotlinSupport)
5 | * [Kotlin Gradle Plugin](#KotlinGradlePlugin)
6 | * [Use Kotlin to Write Gradle Script](#UseKotlintoWriteGradleScript)
7 | * [UI in Kotlin](#UIinKotlin)
8 | * [Handling Kotlin Code](#HandlingKotlinCode)
9 | * [警告](#警告)
10 | * [Examples](#Examples)
11 | * [参考文献](#参考文献)
12 |
13 | ## Why Kotlin?
14 |
15 | 使用Kotlin为IntelliJ平台编写插件与使用Java编写插件非常相似。 现有的插件开发人员可以通过使用与IntelliJ平台捆绑在一起的[J2K编译器](https://kotlinlang.org/docs/tutorials/mixing-java-kotlin-intellij.html#converting-an-existing-java-file-to-kotlin-with-j2k)(版本143. +)将样板Java类转换为Kotlin等效类来开始使用,并且开发人员可以轻松地将Kotlin类与现有Java代码混合和匹配。
16 |
17 | 除了[null安全](https://kotlinlang.org/docs/reference/null-safety.html)和[类型安全构建器](https://kotlinlang.org/docs/reference/type-safe-builders.html)之外,Kotlin语言还为插件开发提供了许多方便的功能,这些功能使插件更易于阅读和维护。 就像Android的Kotlin一样,IntelliJ平台大量使用了回调,这些回调很容易在Kotlin中表示为[lambda](https://kotlinlang.org/docs/reference/lambdas.html)。
18 |
19 | 同样,通过扩展在IntelliJ IDEA中自定义内部类的行为很容易。 例如,通常的做法是保护日志记录语句以避免参数构造的开销,从而在使用日志时导致以下情况:
20 | ```java
21 | if (logger.isDebugEnabled()) {
22 | logger.debug("...");
23 | }
24 | ```
25 | 通过声明以下扩展方法,我们可以在Kotlin中更简洁地实现相同的结果:
26 | ```kotlin
27 | inline fun Logger.debug(lazyMessage: () -> String) {
28 | if (isDebugEnabled) {
29 | debug(lazyMessage())
30 | }
31 | }
32 | ```
33 |
34 | 现在,我们可以直接编写`logger.debug { "..." }`来获得轻量级日志记录的所有好处,而无需赘述。 通过实践,您将能够识别IntelliJ平台中的许多惯用法,这些惯用法可以用Kotlin简化。
35 |
36 | ## Adding Kotlin Support
37 |
38 | > Tip: [GitHub模板](https://jetbrains.org/intellij/sdk/docs/tutorials/github_template.html)使用Kotlin提供了一个预配置的项目。
39 |
40 | 面向IntelliJ平台143及更高版本的插件易于迁移:只需开始编写Kotlin。 IDE已经捆绑了必要的Kotlin插件和库,无需进一步配置。 有关详细说明,请参阅[Kotlin文档](https://kotlinlang.org/docs/tutorials/getting-started.html)。
41 |
42 | ## Kotlin Gradle Plugin
43 |
44 | 对于已经使用Gradle构建系统的插件,或者需要对Kotlin构建过程进行精确控制的插件,我们建议使用`kotlin-gradle-plugin`。 这个Gradle插件以可控和可复制的方式极大地简化了Kotlin项目的构建。
45 |
46 | 您的build.gradle文件可能如下所示:
47 | ```groovy
48 | plugins {
49 | id "java"
50 | id "org.jetbrains.kotlin.jvm" version "1.3.72"
51 | id "org.jetbrains.intellij" version "0.4.21"
52 | }
53 |
54 | apply plugin: "kotlin"
55 | apply plugin: "org.jetbrains.intellij"
56 |
57 | group "com.example"
58 | version "0.0.1"
59 |
60 | sourceCompatibility = 1.8
61 | targetCompatibility = 1.8
62 |
63 | compileKotlin {
64 | kotlinOptions.jvmTarget = "1.8"
65 | }
66 | compileTestKotlin {
67 | kotlinOptions.jvmTarget = "1.8"
68 | }
69 |
70 | repositories {
71 | mavenCentral()
72 | }
73 |
74 | dependencies {
75 | implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.72")
76 | }
77 |
78 | intellij {
79 | version = "2020.1"
80 | pluginName = "Example"
81 | updateSinceUntilBuild = false
82 | }
83 | ```
84 |
85 | ### Use Kotlin to Write Gradle Script
86 |
87 | 从4.4开始,Gradle支持build.gradle.kts,这是用Kotlin编写的build.gradle的替代方案。
88 |
89 | 有很多不错的资源可供您学习如何使用Kotlin脚本为IntelliJ插件编写构建脚本,例如intellij-rust,julia-intellij,covscript-intellij或zig-intellij。
90 |
91 | build.gradle.kts基本上看起来像:
92 | ```groovy
93 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
94 |
95 | plugins {
96 | id("java")
97 | id("org.jetbrains.kotlin.jvm") version "1.3.72"
98 | id("org.jetbrains.intellij") version "0.4.21"
99 | }
100 |
101 | group = "com.your.company.name"
102 | version = "0.1-SNAPSHOT"
103 |
104 | tasks.withType {
105 | sourceCompatibility = "1.8"
106 | targetCompatibility = "1.8"
107 | }
108 | listOf("compileKotlin", "compileTestKotlin").forEach {
109 | tasks.getByName(it) {
110 | kotlinOptions.jvmTarget = "1.8"
111 | }
112 | }
113 |
114 | repositories {
115 | mavenCentral()
116 | }
117 |
118 | dependencies {
119 | implementation(kotlin("stdlib-jdk8"))
120 | }
121 |
122 | intellij {
123 | version = "2020.1"
124 | pluginName = 'Example'
125 | updateSinceUntilBuild = false
126 | }
127 | ```
128 |
129 | ## UI in Kotlin
130 |
131 | 用Kotlin创建用户界面的最佳方法是使用[类型安全的DSL](https://jetbrains.org/intellij/sdk/docs/user_interface_components/kotlin_ui_dsl.html)来构建forms。 当前不支持与Kotlin一起使用GUI设计器
132 |
133 | ## Handling Kotlin Code
134 |
135 | 如果插件处理Kotlin代码(例如提供检查),则需要添加对Kotlin插件(Plugin ID `org.jetbrains.kotlin`)的依赖。
136 |
137 | ## 警告
138 |
139 | 插件必须使用Kotlin类在插件配置文件中实现声明。 在注册extension时,平台使用依赖项注入框架来实例化这些类。 因此,插件不得使用Kotlin对象来实现任何`plugin.xml`声明。
140 |
141 | ## Examples
142 |
143 | 有许多基于IntelliJ平台构建的开源Kotlin项目。 有关可利用IntelliJ平台构建开发人员工具的Kotlin语言的最新示例和应用程序的现成资源,开发人员可以从以下项目中获得启发:
144 |
145 | [IntelliJ-presentation-assistant](https://github.com/chashnikov/IntelliJ-presentation-assistant)
146 |
147 | [Rust](https://github.com/intellij-rust/intellij-rust)
148 |
149 | [HashiCorp Terraform / HCL language support](https://github.com/VladRassokhin/intellij-hcl)
150 |
151 | [TeXiFy IDEA](https://github.com/Hannah-Sten/TeXiFy-IDEA)
152 |
153 | [Makefile support](https://github.com/kropp/intellij-makefile)
154 |
155 | ## 参考文献
156 |
157 | [Kotlin for Plugin Developers](https://jetbrains.org/intellij/sdk/docs/tutorials/kotlin.html)
158 |
159 | [MvpAutoCodePlus](https://github.com/longforus/MvpAutoCodePlus)
160 |
--------------------------------------------------------------------------------
/IdeaPluginStudy/src/main/java/com/lkl/plugin/codegenerator/config/MemberSelectionConfig.java:
--------------------------------------------------------------------------------
1 | package com.lkl.plugin.codegenerator.config;
2 |
3 | import javax.xml.bind.annotation.XmlAccessType;
4 | import javax.xml.bind.annotation.XmlAccessorType;
5 | import javax.xml.bind.annotation.XmlRootElement;
6 |
7 | @XmlRootElement(name = "memberSelection")
8 | @XmlAccessorType(XmlAccessType.FIELD)
9 | public class MemberSelectionConfig implements PipelineStep {
10 | public boolean filterConstantField = true;
11 | public boolean filterEnumField = false;
12 | public boolean filterTransientModifier = false;
13 | public boolean filterStaticModifier = true;
14 | public boolean filterLoggers = true;
15 | public String filterFieldName = "";
16 | public String filterFieldType = "";
17 | public String filterMethodName = "";
18 | public String filterMethodType = "";
19 | public boolean enableMethods = false;
20 | public String providerTemplate = DEFAULT_TEMPLATE;
21 | public boolean allowMultiSelection = true;
22 | public boolean allowEmptySelection = true;
23 | public int sortElements = 0;
24 | public String postfix = "";
25 | public boolean enabled = true;
26 |
27 | @Override public String type() {
28 | return "member-selection";
29 | }
30 |
31 | @Override
32 | public String postfix() {
33 | return postfix;
34 | }
35 |
36 | @Override
37 | public void postfix(String postfix) {
38 | this.postfix = postfix;
39 | }
40 |
41 | @Override
42 | public boolean enabled() {
43 | return enabled;
44 | }
45 |
46 | @Override
47 | public void enabled(boolean enabled) {
48 | this.enabled = enabled;
49 | }
50 |
51 | @Override
52 | public boolean equals(Object o) {
53 | if (this == o) return true;
54 | if (o == null || getClass() != o.getClass()) return false;
55 |
56 | MemberSelectionConfig that = (MemberSelectionConfig) o;
57 |
58 | if (filterConstantField != that.filterConstantField) return false;
59 | if (filterEnumField != that.filterEnumField) return false;
60 | if (filterTransientModifier != that.filterTransientModifier) return false;
61 | if (filterStaticModifier != that.filterStaticModifier) return false;
62 | if (filterLoggers != that.filterLoggers) return false;
63 | if (enableMethods != that.enableMethods) return false;
64 | if (allowMultiSelection != that.allowMultiSelection) return false;
65 | if (allowEmptySelection != that.allowEmptySelection) return false;
66 | if (sortElements != that.sortElements) return false;
67 | if (enabled != that.enabled) return false;
68 | if (filterFieldName != null ? !filterFieldName.equals(that.filterFieldName) : that.filterFieldName != null)
69 | return false;
70 | if (filterFieldType != null ? !filterFieldType.equals(that.filterFieldType) : that.filterFieldType != null)
71 | return false;
72 | if (filterMethodName != null ? !filterMethodName.equals(that.filterMethodName) : that.filterMethodName != null)
73 | return false;
74 | if (filterMethodType != null ? !filterMethodType.equals(that.filterMethodType) : that.filterMethodType != null)
75 | return false;
76 | if (providerTemplate != null ? !providerTemplate.equals(that.providerTemplate) : that.providerTemplate != null)
77 | return false;
78 | return postfix != null ? postfix.equals(that.postfix) : that.postfix == null;
79 | }
80 |
81 | @Override
82 | public int hashCode() {
83 | int result = (filterConstantField ? 1 : 0);
84 | result = 31 * result + (filterEnumField ? 1 : 0);
85 | result = 31 * result + (filterTransientModifier ? 1 : 0);
86 | result = 31 * result + (filterStaticModifier ? 1 : 0);
87 | result = 31 * result + (filterLoggers ? 1 : 0);
88 | result = 31 * result + (filterFieldName != null ? filterFieldName.hashCode() : 0);
89 | result = 31 * result + (filterFieldType != null ? filterFieldType.hashCode() : 0);
90 | result = 31 * result + (filterMethodName != null ? filterMethodName.hashCode() : 0);
91 | result = 31 * result + (filterMethodType != null ? filterMethodType.hashCode() : 0);
92 | result = 31 * result + (enableMethods ? 1 : 0);
93 | result = 31 * result + (providerTemplate != null ? providerTemplate.hashCode() : 0);
94 | result = 31 * result + (allowMultiSelection ? 1 : 0);
95 | result = 31 * result + (allowEmptySelection ? 1 : 0);
96 | result = 31 * result + sortElements;
97 | result = 31 * result + (postfix != null ? postfix.hashCode() : 0);
98 | result = 31 * result + (enabled ? 1 : 0);
99 | return result;
100 | }
101 |
102 | private static String DEFAULT_TEMPLATE = "## set `availableMembers` to provide the members to select\n"
103 | + "## set `selectedMembers` to select the members initially, set nothing to select all\n"
104 | + "## Note that it should be type List or List\n"
105 | + "## And the selected result will be\n"
106 | + "## - fields1: List where `1` is the step number that you specified\n"
107 | + "## - methods1: List\n"
108 | + "## - members: List\n"
109 | + "#set($availableMembers = $class0.members)\n";
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/docs/base/helloWorld.md:
--------------------------------------------------------------------------------
1 | # 编写你的第一个plugin Hello World
2 |
3 | 编程入门从Hello World开始。
4 |
5 | * [下载IntelliJ IDEA](#下载IntelliJIDEA)
6 | * [创建项目](#创建项目)
7 | * [创建Action](#创建Action)
8 | * [plugin.xml](#pluginxml)
9 | * [运行](#运行)
10 | * [卸载插件](#卸载插件)
11 | * [打包插件并在AndroidStudio中安装](#打包插件并在AndroidStudio中安装)
12 |
13 | 通常我们开发的IntelliJ平台插件主要分为如下几类:
14 |
15 | * **自定义编程语言的支持(Custom language support)**:包括语法高亮、文件类型识别、代码格式化、代码查看和自动补全等等
16 | * **框架集成(Framework integration)**:其实就是类似基于IntelliJ开发一个IDE出来,比如AndroidStudio 将Android SDK集成进IntelliJ。其他的插件如Java EE中的Spring、Struts等framework集成到IntelliJ。使用户在IntelliJ上面使用特定的框架更方便。
17 | * **工具集成(Tool integration)**:对IntelliJ定制一些个性化或者是实用的工具。
18 | * **附加UI(User interface add-ons)**:对标准的UI界面进行修改,如在编辑框里加一个背景图片等。
19 |
20 | ## 下载IntelliJ IDEA
21 |
22 | > https://www.jetbrains.com/idea/
23 |
24 | ## 创建项目
25 |
26 | 选择“**File>New>Project…**”,将Project选择为**IntelliJ Platform Plugin**,然后再点击Next。如下图所示:
27 |
28 | 
29 |
30 | 填写Project名称及项目保存路径,其中Project Name可以认为是插件名称。点击Finish,如下图所示:
31 |
32 | 
33 |
34 | 完成后,创建的项目结构如下所示:
35 |
36 | 
37 |
38 | 我们比较关心的主要是`src`目录和`resources/META-INF/plugin.xml`文件。`src`目录存放的是插件对应的Java源码,`resources/META-INF/plugin.xml`是配置Action的文件,关于Action后面讲,现在暂时可以将`resources/META-INF/plugin.xml`看成是插件的配置文件。
39 |
40 | ## 创建Action
41 |
42 | 我们在IntelliJ自定义的插件可以添加到菜单项目(如右键菜单中)或者是放在工具栏中。当用户点击时触发一个动作事件,IntelliJ则会回调`AnAction`类的`actionPerformed`函数。因此我们只需重写`actionPerformed`函数即可。
43 | 在`src`目录中创建包名:`com.lkl.plugin`,然后,在`com.lkl.plugin`中右键 New -> Action 创建一个Action,类为HelloWorldPlugin.java,如下图所示:
44 |
45 | 
46 |
47 | HelloWorldPlugin继承`AnAction`类,并重写`actionPerformed`函数
48 |
49 | ```java
50 | package com.lkl.plugin.base;
51 |
52 | import com.intellij.openapi.actionSystem.AnAction;
53 | import com.intellij.openapi.actionSystem.AnActionEvent;
54 | import com.intellij.openapi.actionSystem.PlatformDataKeys;
55 | import com.intellij.openapi.project.Project;
56 | import com.intellij.openapi.ui.Messages;
57 |
58 | /**
59 | * Created by likunlun on 2020/7/11.
60 | */
61 | public class HelloWorldPlugin extends AnAction {
62 |
63 | @Override
64 | public void actionPerformed(AnActionEvent e) {
65 | // TODO: insert action logic here
66 | Project project = e.getData(PlatformDataKeys.PROJECT);
67 | Messages.showMessageDialog(project, "Hello World!", "Information", Messages.getInformationIcon());
68 | }
69 | }
70 | ```
71 |
72 | ## plugin.xml
73 |
74 | 通过上一步生成的Action会在`plugin.xml`中的``标签中添加``子标签,如下所示:
75 |
76 | ```xml
77 |
78 |
79 |
81 |
82 |
83 |
84 |
85 | ```
86 |
87 | ``标签属性的简单说明:
88 |
89 | > **id**:作为``标签的唯一标识。一般以`<项目名>.<类名>`方式。
90 | >
91 | > **class**:即我们自定义的`AnAction`类
92 | >
93 | > **text**:显示的文字,如我们自定义的插件放在菜单列表中,这个文字就是对应的菜单项
94 | >
95 | > **description**:对这个`AnAction`的描述
96 |
97 |
98 | 另外还有``标签,这个标签指定我们自定义的插件应该放入到哪个菜单下面。在IntelliJ IDEA菜单栏中有很多菜单如File、Edit、View、Navigate、Code、……、Help等。他们的ID一般是菜单名+Menu的方式。比如,我们想将我们自定义的插件放到Help菜单中,作为Help菜单的子选项。那么在``标签中指定`group-id="HelpMenu"`。``标签的anchor属性用于描述位置,主要有四个选项:`first、last、before、after`。他们的含义如下:
99 |
100 | > first:放在最前面
101 | >
102 | > last:放在最后
103 | >
104 | > before:放在relative-to-action属性指定的ID的前面
105 | >
106 | > after:放在relative-to-action属性指定的ID的后面
107 |
108 | `relative-to-action`也是``的属性。
109 |
110 | ``标签用于描述快捷键,主要关注2个属性:`keymap`和`first-keystroke`。`keymap`使用默认值(`$default`)就好,`first-keystroke`用于指定快捷键。
111 |
112 | ## 运行
113 |
114 | 点击运行。会发现,运行时是自动再启动新的IntelliJ IDEA。而新启动的IntelliJ IDEA由于没有可打开的项目会停留在如下界面:
115 |
116 | 
117 |
118 | 为了能查看到我们的插件,可以点击Create New Project或者是导入项目,总之,让它正确进入到开发界面就好。
119 |
120 | 接下来,点击help菜单,会看到如下:
121 |
122 | 
123 |
124 | 点击·”HelloWorld”项,运行如下:
125 |
126 | 
127 |
128 | ## 卸载插件
129 |
130 | 当我们按照上面的方面再创建一个插件时,发现上一次的插件还会出现。而且我们创建的新的插件不会出现,这是什么原因呢?这主要是,我们没有修改插件名称,并且没有修改版本。这样的话自然就没有覆盖原先的插件了。
131 |
132 | 因此我们有2种方法:
133 | * 第一种就是将原来的插件卸载
134 | * 第二种就是将新建的插件名称与原先的区分开来(在plugin.xml中 标签中指定)
135 |
136 | 将原来的插件卸载,首先,点击“File>Settings>Plugins”,如下图:
137 |
138 | 
139 |
140 | 找到插件名称,这里也就是`“Plugin display name here”`,因为一开始我们没有修改插件名称,这个名词是自动生成的。然后点击`Uninstall`,最后重启或者是关闭IntelliJ IDEA完成卸载。
141 |
142 | ## 打包插件并在AndroidStudio中安装
143 |
144 | 在IntelliJ中打包。点击`“Build > Prepare Plugin Module 'IdeaPluginStudy' For Deployment”`,如下图:
145 |
146 | 
147 |
148 | 这时在 IdeaPluginStudy 项目中多了一个`IdeaPluginStudy.jar`文件,如下图:
149 |
150 | 
151 |
152 | 这个文件即为我们导出的插件。接下来打开AndroidStudio,点击`“File>Settings>Plugins”`
153 |
154 | 
155 |
156 | 点击“install plugin from disk…”,将 IdeaPluginStudy.jar包加入即可完成安装。
--------------------------------------------------------------------------------