Skip to content

Commit f8a9f45

Browse files
committed
初步添加了 自动清单注册和自动生成layout的功能
1 parent 3d549f1 commit f8a9f45

File tree

5 files changed

+197
-60
lines changed

5 files changed

+197
-60
lines changed

build.gradle

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
buildscript {
22
ext.kotlin_version = '1.3.61'
3-
43
repositories {
54
// maven { url 'http://192.168.2.39:8908/repository/maven-public/' }
65
maven { url 'https://maven.aliyun.com/repository/public' }
6+
google()
77
mavenCentral()
8-
maven { url "https://www.jetbrains.com/intellij-repository/releases" }
9-
maven { url "https://jetbrains.bintray.com/intellij-third-party-dependencies" }
108
}
119
dependencies {
1210
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
@@ -39,9 +37,8 @@ targetCompatibility = 1.8
3937
repositories {
4038
// maven{ url 'http://192.168.2.39:8908/repository/maven-public/'}
4139
maven { url 'https://maven.aliyun.com/repository/public' }
40+
google()
4241
mavenCentral()
43-
maven { url "https://www.jetbrains.com/intellij-repository/releases" }
44-
maven { url "https://jetbrains.bintray.com/intellij-third-party-dependencies" }
4542
}
4643

4744
compileKotlin {
@@ -75,11 +72,12 @@ dependencies {
7572
compileOnly fileTree(dir: "$StudioCompilePath/plugins/android/lib", include: ['*.jar'])
7673
compileOnly fileTree(dir: "$StudioCompilePath/plugins/java/lib", include: ['*.jar'])
7774
compileOnly fileTree(dir: "$StudioCompilePath/lib", include: ['*.jar'])
75+
7876
testCompile fileTree(dir: "$StudioCompilePath/plugins/android/lib", include: ['*.jar'])
7977
testCompile fileTree(dir: "$StudioCompilePath/plugins/java/lib", include: ['*.jar'])
8078
testCompile fileTree(dir: "$StudioCompilePath/lib", include: ['*.jar'])
8179
// compile "com.jetbrains.intellij.java:java-psi:192.7142.36"
82-
// compileOnly "com.jetbrains.intellij.java:java-impl:192.7142.36"
80+
compileOnly "com.android.tools.build:gradle:3.6.1"
8381
// compileOnly "com.jetbrains.intellij.java:java:192.7142.36"
8482
// compile 'com.squareup:javapoet:1.11.0'
8583
// testCompile group: 'junit', name: 'junit', version: '4.12'

src/main/kotlin/com/longforus/mvpautocodeplus/MainAction.kt

Lines changed: 69 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,14 @@ import com.intellij.openapi.actionSystem.*
88
import com.intellij.openapi.application.WriteActionAware
99
import com.intellij.openapi.fileEditor.FileEditorManager
1010
import com.intellij.openapi.fileEditor.TextEditor
11+
import com.intellij.openapi.module.ModuleUtil
1112
import com.intellij.openapi.project.Project
12-
import com.intellij.psi.PsiClass
13-
import com.intellij.psi.PsiDirectory
14-
import com.intellij.psi.PsiFile
15-
import com.intellij.psi.PsiJavaFile
13+
import com.intellij.psi.*
1614
import com.intellij.util.PlatformIcons
17-
import com.longforus.mvpautocodeplus.maker.TemplateMaker
18-
import com.longforus.mvpautocodeplus.maker.TemplateParamFactory
19-
import com.longforus.mvpautocodeplus.maker.createFileFromTemplate
20-
import com.longforus.mvpautocodeplus.maker.overrideOrImplementMethods
15+
import com.longforus.mvpautocodeplus.config.ItemConfigBean
16+
import com.longforus.mvpautocodeplus.maker.*
2117
import com.longforus.mvpautocodeplus.ui.EnterKeywordDialog
18+
import org.jetbrains.android.facet.AndroidFacet
2219
import org.jetbrains.kotlin.psi.KtFile
2320
import com.intellij.openapi.application.runWriteAction as runWriteAction1
2421

@@ -31,30 +28,31 @@ import com.intellij.openapi.application.runWriteAction as runWriteAction1
3128
class MainAction : AnAction("Generate MVP Code", "auto make mvp code", PlatformIcons.CLASS_ICON), WriteActionAware {
3229
var project: Project? = null
3330
lateinit var mSelectedState: PropertiesComponent
34-
fun createFile(enterName: String, templateName: String, dir: PsiDirectory, superImplName: String, contract: PsiFile? = null, fileName: String = enterName):
35-
PsiFile? {
36-
val template = TemplateMaker.getTemplate(templateName, project!!) ?: return null
31+
fun createFile(enterName: String, templateName: String, dir: PsiDirectory, superImplName: String, contract: PsiFile? = null, fileName: String = enterName): Pair<PsiFile?,
32+
PsiClass?> {
33+
var clazz: PsiClass? = null
34+
val template = TemplateMaker.getTemplate(templateName, project!!) ?: return null to null
3735
val liveTemplateDefaultValues = TemplateParamFactory.getParam4TemplateName(templateName, enterName, superImplName, contract, mSelectedState)
3836
val psiFile = createFileFromTemplate(fileName, template, dir, null, false, liveTemplateDefaultValues, mSelectedState.getValue(COMMENT_AUTHOR))
3937
if (!templateName.contains("Contract")) {
4038
val openFile = FileEditorManager.getInstance(project!!).openFile(psiFile!!.virtualFile, false)
4139
val textEditor = openFile[0] as TextEditor
42-
var clazz: PsiClass? = null
40+
4341
if (psiFile is PsiJavaFile) {
4442
if (psiFile.classes.isEmpty()) {
45-
return psiFile
43+
return psiFile to null
4644
}
4745
clazz = psiFile.classes[0]
4846
} else if (psiFile is KtFile) {
4947
if (psiFile.classes.isEmpty()) {
50-
return psiFile
48+
return psiFile to null
5149
}
5250
clazz = psiFile.classes[0]
5351
}
5452
FeatureUsageTracker.getInstance().triggerFeatureUsed(ProductivityFeatureNames.CODEASSISTS_OVERRIDE_IMPLEMENT)
5553
overrideOrImplementMethods(project!!, textEditor.editor, clazz!!, true)
5654
}
57-
return psiFile
55+
return psiFile to clazz
5856
}
5957

6058
override fun actionPerformed(e: AnActionEvent) {
@@ -72,57 +70,74 @@ class MainAction : AnAction("Generate MVP Code", "auto make mvp code", PlatformI
7270
// Messages.showErrorDialog("Super IView Interface name is null ! $GOTO_SETTING", "Error")
7371
// return
7472
// }
73+
74+
//NewAndroidComponentDialog
75+
7576
EnterKeywordDialog.getDialog(project) {
7677
mSelectedState = it.state
78+
val module = ModuleUtil.findModuleForFile(dir.virtualFile, project!!)
79+
val facet = AndroidFacet.getInstance(module!!)
7780
runWriteAction1 {
7881
if (it.isJava) {
79-
val contractJ = createFile(it.name, if (it.generateModel) CONTRACT_TP_NAME_JAVA else CONTRACT_TP_NO_MODEL_NAME_JAVA, getSubDir(dir, CONTRACT),
80-
"")
81-
if (!it.vImpl.isEmpty() && !it.vImpl.startsWith(IS_NOT_SET)) {
82-
val sdV = getSubDir(dir, VIEW)
83-
if (it.isActivity) {
84-
createFile(it.name, VIEW_IMPL_TP_ACTIVITY_JAVA, sdV, it.vImpl, contractJ)
85-
} else {
86-
createFile(it.name, VIEW_IMPL_TP_FRAGMENT_JAVA, sdV, it.vImpl, contractJ)
87-
}
88-
}
89-
if (!it.pImpl.isEmpty()) {
90-
val sdP = getSubDir(dir, PRESENTER)
91-
createFile(it.name, PRESENTER_IMPL_TP_JAVA, sdP, it.pImpl, contractJ)
92-
}
93-
if (!it.mImpl.isEmpty() && it.generateModel) {
94-
val sdM = getSubDir(dir, MODEL)
95-
createFile(it.name, MODEL_IMPL_TP_JAVA, sdM, it.mImpl, contractJ)
96-
}
97-
82+
doJavaCreate(it, dir, facet)
9883
} else {
99-
val contractK = createFile(it.name, if (it.generateModel) CONTRACT_TP_NAME_KOTLIN else CONTRACT_TP_NO_MODEL_NAME_KOTLIN, getSubDir(dir, CONTRACT), "",
100-
fileName = getContractName(it
101-
.name))
102-
103-
if (!it.vImpl.isEmpty() && !it.vImpl.startsWith(IS_NOT_SET)) {
104-
val sdV = getSubDir(dir, VIEW)
105-
if (it.isActivity) {
106-
createFile(it.name, VIEW_IMPL_TP_ACTIVITY_KOTLIN, sdV, it.vImpl, contractK, "${it.name}Activity")
107-
} else {
108-
createFile(it.name, VIEW_IMPL_TP_FRAGMENT_KOTLIN, sdV, it.vImpl, contractK, "${it.name}Fragment")
109-
}
110-
}
111-
if (!it.pImpl.isEmpty()) {
112-
val sdP = getSubDir(dir, PRESENTER)
113-
createFile(it.name, PRESENTER_IMPL_TP_KOTLIN, sdP, it.pImpl, contractK, "${it.name}${TemplateParamFactory.getPresenterOrViewModel(it.pImpl)}")
114-
}
115-
if (!it.mImpl.isEmpty() && it.generateModel) {
116-
val sdM = getSubDir(dir, MODEL)
117-
createFile(it.name, MODEL_IMPL_TP_KOTLIN, sdM, it.mImpl, contractK, "${it.name}Model")
118-
}
84+
doKtCreate(it, dir, facet)
11985
}
12086
}
87+
}
88+
}
12189

90+
private fun doKtCreate(it: ItemConfigBean, dir: PsiDirectory, facet: AndroidFacet?) {
91+
val contractK = createFile(it.name, if (it.generateModel) CONTRACT_TP_NAME_KOTLIN else CONTRACT_TP_NO_MODEL_NAME_KOTLIN, getSubDir(dir, CONTRACT), "",
92+
fileName = getContractName(it
93+
.name))
94+
95+
if (it.vImpl.isNotEmpty() && !it.vImpl.startsWith(IS_NOT_SET)) {
96+
val sdV = getSubDir(dir, VIEW)
97+
if (it.isActivity) {
98+
val activityKt = createFile(it.name, VIEW_IMPL_TP_ACTIVITY_KOTLIN, sdV, it.vImpl, contractK.first, "${it.name}Activity")
99+
CompleteRegister.registerActivity(activityKt.second, JavaDirectoryService.getInstance().getPackage(dir), facet!!, "")
100+
doCreateLayoutFile(activityKt.second, dir, facet, false)
101+
} else {
102+
val fragmentKt = createFile(it.name, VIEW_IMPL_TP_FRAGMENT_KOTLIN, sdV, it.vImpl, contractK.first, "${it.name}Fragment")
103+
doCreateLayoutFile(fragmentKt.second, dir, facet!!, false)
104+
}
105+
}
106+
if (it.pImpl.isNotEmpty()) {
107+
val sdP = getSubDir(dir, PRESENTER)
108+
createFile(it.name, PRESENTER_IMPL_TP_KOTLIN, sdP, it.pImpl, contractK.first, "${it.name}${TemplateParamFactory.getPresenterOrViewModel(it.pImpl)}")
122109
}
110+
if (it.mImpl.isNotEmpty() && it.generateModel) {
111+
val sdM = getSubDir(dir, MODEL)
112+
createFile(it.name, MODEL_IMPL_TP_KOTLIN, sdM, it.mImpl, contractK.first, "${it.name}Model")
113+
}
114+
}
123115

116+
private fun doJavaCreate(it: ItemConfigBean, dir: PsiDirectory, facet: AndroidFacet?) {
117+
val contractJ = createFile(it.name, if (it.generateModel) CONTRACT_TP_NAME_JAVA else CONTRACT_TP_NO_MODEL_NAME_JAVA, getSubDir(dir, CONTRACT),
118+
"")
119+
if (it.vImpl.isNotEmpty() && !it.vImpl.startsWith(IS_NOT_SET)) {
120+
val sdV = getSubDir(dir, VIEW)
121+
if (it.isActivity) {
122+
val activityJava = createFile(it.name, VIEW_IMPL_TP_ACTIVITY_JAVA, sdV, it.vImpl, contractJ.first)
123+
CompleteRegister.registerActivity(activityJava.second, JavaDirectoryService.getInstance().getPackage(dir), facet!!, "")
124+
doCreateLayoutFile(activityJava.second, dir, facet, true)
125+
} else {
126+
val fragmentJava = createFile(it.name, VIEW_IMPL_TP_FRAGMENT_JAVA, sdV, it.vImpl, contractJ.first)
127+
doCreateLayoutFile(fragmentJava.second, dir, facet!!, true)
128+
}
129+
}
130+
if (it.pImpl.isNotEmpty()) {
131+
val sdP = getSubDir(dir, PRESENTER)
132+
createFile(it.name, PRESENTER_IMPL_TP_JAVA, sdP, it.pImpl, contractJ.first)
133+
}
134+
if (it.mImpl.isNotEmpty() && it.generateModel) {
135+
val sdM = getSubDir(dir, MODEL)
136+
createFile(it.name, MODEL_IMPL_TP_JAVA, sdM, it.mImpl, contractJ.first)
137+
}
124138
}
125139

140+
126141
fun getSubDir(dir: PsiDirectory, dirName: String): PsiDirectory {
127142
return if (dir.name == CONTRACT) {
128143
if (dirName == CONTRACT) {
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.longforus.mvpautocodeplus.maker
2+
3+
import com.intellij.openapi.vfs.ReadonlyStatusHandler
4+
import com.intellij.psi.PsiClass
5+
import com.intellij.psi.PsiPackage
6+
import org.jetbrains.android.dom.manifest.Application
7+
import org.jetbrains.android.dom.manifest.ApplicationComponent
8+
import org.jetbrains.android.dom.manifest.Manifest
9+
import org.jetbrains.android.dom.resources.ResourceValue
10+
import org.jetbrains.android.facet.AndroidFacet
11+
import org.jetbrains.android.facet.AndroidRootUtil
12+
import org.jetbrains.android.util.AndroidUtils
13+
14+
/**
15+
* @describe
16+
* @author longforus
17+
* @date 2020/3/18 15:11
18+
*/
19+
object CompleteRegister {
20+
21+
fun registerActivity(aClass: PsiClass?, aPackage: PsiPackage?, facet: AndroidFacet, label: String?) {
22+
val manifestFile = AndroidRootUtil.getManifestFile(facet)
23+
if (manifestFile != null && ReadonlyStatusHandler.ensureFilesWritable(facet.module.project, *arrayOf(manifestFile))) {
24+
val manifest = AndroidUtils.loadDomElement(facet.module, manifestFile,
25+
Manifest::class.java)
26+
if (manifest != null) {
27+
val packageName = manifest.getPackage().value
28+
if (packageName == null || packageName.isEmpty()) {
29+
manifest.getPackage().setValue(aPackage?.qualifiedName)
30+
}
31+
val application = manifest.application
32+
if (application != null) {
33+
val component = addToManifest( aClass!!, application)
34+
if (component != null && !label.isNullOrEmpty()) {
35+
component.label.setValue(ResourceValue.literal(label))
36+
}
37+
}
38+
}
39+
}
40+
}
41+
42+
43+
fun addToManifest(aClass: PsiClass, application: Application): ApplicationComponent? {
44+
val activity = application.addActivity()
45+
activity.activityClass.value = aClass
46+
return activity
47+
}
48+
49+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.longforus.mvpautocodeplus.maker
2+
3+
import com.android.resources.ResourceFolderType
4+
import com.intellij.openapi.application.ApplicationManager
5+
import com.intellij.openapi.command.WriteCommandAction
6+
import com.intellij.openapi.util.io.FileUtil
7+
import com.intellij.psi.*
8+
import com.intellij.psi.codeStyle.CodeStyleManager
9+
import com.intellij.psi.codeStyle.JavaCodeStyleManager
10+
import org.jetbrains.android.actions.CreateResourceFileAction
11+
import org.jetbrains.android.dom.manifest.Manifest
12+
import org.jetbrains.android.facet.AndroidFacet
13+
import org.jetbrains.android.util.AndroidResourceUtil
14+
15+
/**
16+
* @describe
17+
* @author longforus
18+
* @date 2020/3/18 16:07
19+
*/
20+
@Throws(Exception::class)
21+
fun doCreateLayoutFile(element: PsiClass?, directory: PsiDirectory, facet: AndroidFacet, isJava: Boolean): PsiElement? {
22+
return if (element == null) {
23+
null
24+
} else {
25+
val manifest = Manifest.getMainManifest(facet)
26+
val appPackage = manifest?.getPackage()?.value
27+
if (appPackage != null && !appPackage.isEmpty()) {
28+
ApplicationManager.getApplication().invokeLater {
29+
createLayoutFileForActivityOrFragment(facet, element, appPackage, directory, isJava)
30+
}
31+
}
32+
element
33+
}
34+
}
35+
36+
fun createLayoutFileForActivityOrFragment(facet: AndroidFacet, activityClass: PsiClass, appPackage: String, resDirectory: PsiDirectory, isJava: Boolean) {
37+
if (!facet.isDisposed && activityClass.isValid) {
38+
val className = activityClass.name
39+
if (className != null) {
40+
val layoutFile = CreateResourceFileAction.createFileResource(facet, ResourceFolderType.LAYOUT, null, null, null, true, "Create Layout For '$className'", resDirectory, null, false)
41+
val layoutFileName = layoutFile?.name
42+
if (layoutFileName != null) {
43+
val onCreateMethods = activityClass.findMethodsByName("getLayoutId", false)//todo 生成viewBinding
44+
if (onCreateMethods.size != 1) {
45+
return
46+
}
47+
val onCreateMethod = onCreateMethods[0]
48+
val body = onCreateMethod.body
49+
if (body != null) {
50+
val fieldName = AndroidResourceUtil.getRJavaFieldName(FileUtil.getNameWithoutExtension(layoutFileName))
51+
val layoutFieldRef = "$appPackage.R.layout.$fieldName"
52+
addInflateStatement(body, layoutFieldRef, isJava)
53+
}
54+
}
55+
}
56+
}
57+
}
58+
59+
60+
fun addInflateStatement(body: PsiCodeBlock, layoutFieldRef: String, isJava: Boolean) {
61+
val project = body.project
62+
val statements = body.statements
63+
if (statements.size == 1) {
64+
val statement = statements[0]
65+
WriteCommandAction.writeCommandAction(project, body.containingFile).run<Throwable> {
66+
val newStatement = PsiElementFactory.getInstance(project).createStatementFromText(
67+
"return $layoutFieldRef${if (isJava) ";" else ""}", body)
68+
statement.replace(newStatement)
69+
JavaCodeStyleManager.getInstance(project).shortenClassReferences(body)
70+
CodeStyleManager.getInstance(project).reformat(body)
71+
}
72+
}
73+
}
74+

src/main/kotlin/com/longforus/mvpautocodeplus/maker/MethodImpl.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ fun kotlinDoMultiOverrideImplement(aClass: KtLightClass, project: Project, edito
4646

4747
val chooserObjects = implementMembersHandler.collectMembersToGenerate(
4848
classOrObject).sortedBy { it.descriptor.name.asString() + " in " + it.immediateSuper.containingDeclaration.name.asString() }
49+
4950
writeCommandAction(project, aClass.containingFile).run<Throwable> {
5051
OverrideImplementMembersHandler.generateMembers(editor, classOrObject, chooserObjects, false)
5152
}

0 commit comments

Comments
 (0)