1
+ package cc.unitmesh.openrewrite.provider
2
+
3
+ import cc.unitmesh.devti.provider.RunService
4
+ import com.intellij.execution.ExecutionManager
5
+ import com.intellij.execution.RunManager
6
+ import com.intellij.execution.configurations.ConfigurationTypeUtil
7
+ import com.intellij.execution.configurations.RunConfiguration
8
+ import com.intellij.execution.configurations.RunProfile
9
+ import com.intellij.execution.executors.DefaultRunExecutor
10
+ import com.intellij.execution.runners.ExecutionEnvironmentBuilder
11
+ import com.intellij.openapi.application.runReadAction
12
+ import com.intellij.openapi.project.Project
13
+ import com.intellij.openapi.vfs.VirtualFile
14
+ import com.intellij.psi.PsiElement
15
+ import com.intellij.psi.PsiFile
16
+ import com.intellij.psi.PsiManager
17
+
18
+ class OpenRewriteFileRunService : RunService {
19
+ override fun isApplicable (project : Project , file : VirtualFile ): Boolean {
20
+ return file.extension == " yml" && isOpenWriteFile(project, file)
21
+ }
22
+
23
+ private fun isOpenWriteFile (project : Project , file : VirtualFile ): Boolean {
24
+ try {
25
+ val clazz = Class .forName(" com.intellij.openRewrite.OpenRewriteFileService" )
26
+ val getInstanceMethod = clazz.getDeclaredMethod(" getInstance" )
27
+ val isRecipeMethod = clazz.getDeclaredMethod(" isRecipe" , PsiFile ::class .java)
28
+
29
+ val fileService = getInstanceMethod.invoke(null )
30
+ val psiFile = runReadAction {
31
+ PsiManager .getInstance(project).findFile(file)
32
+ } ? : return false
33
+
34
+ isRecipeMethod.isAccessible = true
35
+
36
+ val result = isRecipeMethod.invoke(fileService, psiFile) as Boolean
37
+ return result
38
+ } catch (e: Exception ) {
39
+ return false
40
+ }
41
+ }
42
+
43
+ override fun runConfigurationClass (project : Project ): Class <out RunProfile >? = null
44
+
45
+ override fun runFile (
46
+ project : Project ,
47
+ virtualFile : VirtualFile ,
48
+ psiElement : PsiElement ? ,
49
+ isFromToolAction : Boolean
50
+ ): String? {
51
+ if (! isOpenWriteFile(project, virtualFile)) {
52
+ return " "
53
+ }
54
+
55
+ val runManager = RunManager .getInstance(project)
56
+ val allSettings = runManager.allSettings
57
+
58
+ val workingPath = virtualFile.parent.path
59
+
60
+ var settings = allSettings.firstOrNull {
61
+ try {
62
+ val config = it.configuration
63
+ val configClass = config::class .java
64
+
65
+ if (configClass.name == " com.intellij.openRewrite.run.OpenRewriteRunConfiguration" ) {
66
+ val getExpandedWorkingDirectoryMethod = configClass.getMethod(" getExpandedWorkingDirectory" )
67
+ val workingDirectory = getExpandedWorkingDirectoryMethod.invoke(config) as ? String
68
+ workingDirectory == workingPath
69
+ } else {
70
+ false
71
+ }
72
+ } catch (e: Exception ) {
73
+ false
74
+ }
75
+ }
76
+
77
+ val list = try {
78
+ getRecipeDescriptors(project, virtualFile) ? : return null
79
+ } catch (e: Exception ) {
80
+ return null
81
+ }
82
+ if (list.isEmpty()) return null
83
+
84
+ if (settings == null ) {
85
+ try {
86
+ val configurationType = ConfigurationTypeUtil .findConfigurationType(" OpenRewriteRunConfigurationType" )!!
87
+ settings = runManager.createConfiguration(" " , configurationType.configurationFactories[0 ])
88
+ val configuration = settings.configuration
89
+
90
+ if (configuration.javaClass.name == " com.intellij.openRewrite.run.OpenRewriteRunConfiguration" ) {
91
+ configureOpenRewrite(configuration, project, virtualFile, list)
92
+ }
93
+
94
+ runManager.setUniqueNameIfNeeded(settings)
95
+ runManager.setTemporaryConfiguration(settings)
96
+ } catch (e: Exception ) {
97
+ return null
98
+ }
99
+ }
100
+
101
+ val builder = ExecutionEnvironmentBuilder .createOrNull(DefaultRunExecutor .getRunExecutorInstance(), settings)
102
+ builder?.let {
103
+ ExecutionManager .getInstance(project).restartRunProfile(it.build())
104
+ }
105
+
106
+ return " "
107
+ }
108
+
109
+ private fun configureOpenRewrite (
110
+ configuration : RunConfiguration ,
111
+ project : Project ,
112
+ virtualFile : VirtualFile ,
113
+ list : java.util.LinkedHashMap <* , * >,
114
+ ) {
115
+ val directoryMethod =
116
+ configuration::class .java.getMethod(" setWorkingDirectory" , String ::class .java)
117
+ val projectRoot = project.basePath ? : " "
118
+ directoryMethod.invoke(configuration, projectRoot)
119
+
120
+ val setConfigLocationMethod =
121
+ configuration::class .java.getMethod(" setConfigLocation" , String ::class .java)
122
+ setConfigLocationMethod.invoke(configuration, virtualFile.path)
123
+
124
+ val setActiveRecipesMethod =
125
+ configuration::class .java.getMethod(" setActiveRecipes" , String ::class .java)
126
+ setActiveRecipesMethod.invoke(configuration, list.keys.first())
127
+
128
+ val nameMethod = configuration::class .java.getMethod(" setGeneratedName" )
129
+ nameMethod.invoke(configuration)
130
+ }
131
+
132
+ private fun getRecipeDescriptors (project : Project , virtualFile : VirtualFile ): LinkedHashMap <* , * >? {
133
+ val clazz = Class .forName(" com.intellij.openRewrite.recipe.OpenRewriteRecipeService" )
134
+ val getInstanceMethod = clazz.getDeclaredMethod(" getInstance" , Project ::class .java)
135
+ val recipeService = getInstanceMethod.invoke(null , project)
136
+ val OpenRewriteType = Class .forName(" com.intellij.openRewrite.recipe.OpenRewriteType" ).getEnumConstants()[0 ]
137
+
138
+ val method =
139
+ clazz.getDeclaredMethod(" getLocalDescriptors" , PsiFile ::class .java, OpenRewriteType ::class .java)
140
+ method.isAccessible = true
141
+
142
+ val psiFile = runReadAction {
143
+ PsiManager .getInstance(project).findFile(virtualFile)
144
+ } ? : return null
145
+
146
+ val list = runReadAction {
147
+ val type = OpenRewriteType ::class .java.enumConstants[0 ]
148
+ method.invoke(recipeService, psiFile, type) as LinkedHashMap <* , * >
149
+ }
150
+
151
+ return list
152
+ }
153
+ }
0 commit comments