Skip to content

Commit de40fb8

Browse files
authored
Add generate settings (#106)
1 parent 26f502b commit de40fb8

File tree

15 files changed

+274
-122
lines changed

15 files changed

+274
-122
lines changed

core/src/main/kotlin/cn/enaium/jimmer/buddy/JimmerBuddy.kt

Lines changed: 60 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import cn.enaium.jimmer.buddy.extensions.wizard.JimmerProjectModel
2323
import cn.enaium.jimmer.buddy.service.NavigationService
2424
import cn.enaium.jimmer.buddy.service.PsiService
2525
import cn.enaium.jimmer.buddy.service.UiService
26+
import cn.enaium.jimmer.buddy.storage.JimmerBuddySetting
2627
import cn.enaium.jimmer.buddy.utility.*
2728
import com.google.devtools.ksp.getClassDeclarationByName
2829
import com.intellij.compiler.CompilerConfiguration
@@ -101,7 +102,7 @@ object JimmerBuddy {
101102

102103
const val INFO_GROUP_ID = "JimmerBuddy.NotificationGroup"
103104

104-
val DEQ = DelayedExecutionQueue(2000)
105+
val DEQ = DelayedExecutionQueue(JimmerBuddySetting.INSTANCE.state.autoGenerateDelay)
105106

106107
object Services {
107108
val PSI: PsiService = ServiceLoader.load(PsiService::class.java, JimmerBuddy::class.java.classLoader).first()
@@ -199,57 +200,69 @@ object JimmerBuddy {
199200

200201
val javaImmutablePsiClassCache = CopyOnWriteArraySet<PsiClass>()
201202

202-
val kotlinImmutableKtClassCache = CopyOnWriteArraySet<KtClass>()
203-
204203
var init = false
205204
var initialized = false
206205

207-
fun init() {
206+
fun init(enable: Boolean = true) {
208207
if (init) return
209208
init = true
210209
project.runWhenSmart {
211210
val projects = findProjects(project.guessProjectDir()?.toNioPath()!!)
212211
CoroutineScope(Dispatchers.IO).launch {
213212
log.info("Project ${project.name} is initializing")
214213
if (project.isJavaProject()) {
215-
sourcesProcessJava(
216-
GenerateProject.generate(
217-
projects,
218-
setOf("main", "test"),
219-
GenerateProject.SourceRootType.JAVA
220-
)
214+
val generateProject = GenerateProject.generate(
215+
projects,
216+
setOf("main", "test"),
217+
GenerateProject.SourceRootType.JAVA
221218
)
222-
dtoProcessJava(
223-
GenerateProject.generate(
224-
projects,
225-
setOf("main", "test"),
226-
GenerateProject.SourceRootType.DTO
219+
project.runReadActionSmart {
220+
generateProject.forEach {
221+
it.sourceFiles.forEach { sourceFile ->
222+
val psiFile =
223+
sourceFile.toFile().toVirtualFile()?.findPsiFile(project) ?: return@forEach
224+
psiFile.getChildOfType<PsiClass>()?.takeIf { it.hasJimmerAnnotation() }?.also {
225+
javaImmutablePsiClassCache.add(it)
226+
}
227+
}
228+
}
229+
}
230+
if (enable) {
231+
sourcesProcessJava(generateProject)
232+
dtoProcessJava(
233+
GenerateProject.generate(
234+
projects,
235+
setOf("main", "test"),
236+
GenerateProject.SourceRootType.DTO
237+
)
227238
)
228-
)
239+
}
229240
} else if (project.isKotlinProject()) {
230-
sourcesProcessKotlin(
231-
GenerateProject.generate(
232-
projects,
233-
setOf("main", "test"),
234-
listOf(GenerateProject.SourceRootType.KOTLIN) +
235-
if (project.isAndroidProject()) {
236-
listOf(
237-
GenerateProject.SourceRootType.JAVA_KOTLIN,
238-
GenerateProject.SourceRootType.JVM_MAIN_KOTLIN,
239-
GenerateProject.SourceRootType.ANDROID_MAIN_KOTLIN
240-
)
241-
} else {
242-
emptyList()
243-
}
241+
if (enable) {
242+
sourcesProcessKotlin(
243+
GenerateProject.generate(
244+
projects,
245+
setOf("main", "test"),
246+
listOf(GenerateProject.SourceRootType.KOTLIN) +
247+
if (project.isAndroidProject()) {
248+
listOf(
249+
GenerateProject.SourceRootType.JAVA_KOTLIN,
250+
GenerateProject.SourceRootType.JVM_MAIN_KOTLIN,
251+
GenerateProject.SourceRootType.ANDROID_MAIN_KOTLIN
252+
)
253+
} else {
254+
emptyList()
255+
}
256+
)
244257
)
245-
)
246-
dtoProcessKotlin(
247-
GenerateProject.generate(
248-
projects,
249-
setOf("main", "test"),
250-
GenerateProject.SourceRootType.DTO
258+
dtoProcessKotlin(
259+
GenerateProject.generate(
260+
projects,
261+
setOf("main", "test"),
262+
GenerateProject.SourceRootType.DTO
263+
)
251264
)
252-
)
265+
}
253266
}
254267
log.info("Project ${project.name} is initialized")
255268
initialized = true
@@ -264,7 +277,6 @@ object JimmerBuddy {
264277

265278
fun reset() {
266279
javaImmutablePsiClassCache.clear()
267-
kotlinImmutableKtClassCache.clear()
268280
init = false
269281
}
270282

@@ -364,14 +376,14 @@ object JimmerBuddy {
364376

365377
val generatedDir = getGeneratedDir(project, projectDir, src) ?: return@runReadActionSmart
366378

367-
val (pe, rootElements, sources) = project.psiClassesToApt(psiCaches, javaImmutablePsiClassCache)
379+
val (pe, rootElements, sources) = project.psiClassesToApt(javaImmutablePsiClassCache)
368380
val currentModule = project.modules.find { it.name.endsWith(".$src") }
369381
val aptOptions = currentModule?.let { module ->
370382
CompilerConfiguration.getInstance(project)
371383
.getAnnotationProcessingConfiguration(module).processorOptions
372384
} ?: emptyMap()
373385

374-
log.info("SourcesProcessJava Project:${projectDir.name}:${src} PsiCaches:${javaImmutablePsiClassCache.size} APTOptions:${aptOptions}")
386+
log.info("SourcesProcessJava Project:${projectDir.name}:${src} APTOptions:${aptOptions}")
375387

376388
val option = createAptOption(
377389
aptOptions,
@@ -414,18 +426,14 @@ object JimmerBuddy {
414426
log.error(e)
415427
}
416428
}
417-
javaImmutablePsiClassCache.addAll(psiCaches)
418429
}
419430
asyncRefreshSources(needRefresh)
420431
}
421432

422433
suspend fun dtoProcessJava(projects: Set<GenerateProject>) {
423434
val needRefresh = mutableListOf<Pair<Source, Path>>()
424435
project.runReadActionSmart {
425-
val (pe, rootElements, sources) = project.psiClassesToApt(
426-
CopyOnWriteArraySet(),
427-
javaImmutablePsiClassCache
428-
)
436+
val (pe, rootElements, sources) = project.psiClassesToApt(emptySet())
429437
projects.forEach { (projectDir, sourceFiles, src) ->
430438
sourceFiles.forEach { sourceFile ->
431439
val currentModule = project.modules.find { it.name.endsWith(".$src") }
@@ -483,25 +491,18 @@ object JimmerBuddy {
483491
val needRefresh = mutableListOf<Pair<Source, Path>>()
484492
projects.forEach { (projectDir, sourceFiles, src) ->
485493
sourceFiles.isEmpty() && return@forEach
486-
val ktClassCaches = CopyOnWriteArraySet<KtClass>()
487494
project.runReadActionSmart {
488-
sourceFiles.forEach { sourceFile ->
489-
val psiFile = sourceFile.toFile().toPsiFile(project) ?: return@forEach
490-
psiFile.getChildOfType<KtClass>()?.takeIf { it.hasJimmerAnnotation() }?.also {
491-
ktClassCaches.add(it)
492-
}
493-
}
494-
495495
val generatedDir = getGeneratedDir(project, projectDir, src) ?: return@runReadActionSmart
496-
497-
val (resolver, environment, sources) = project.ktClassToKsp(
498-
ktClassCaches,
499-
kotlinImmutableKtClassCache
496+
val (resolver, environment, sources) = project.ktClassesToKsp(
497+
sourceFiles.mapNotNull { sourceFile ->
498+
sourceFile.toFile().toPsiFile(project)?.getChildOfType<KtClass>()
499+
?.takeIf { it.hasJimmerAnnotation() }
500+
}.toSet()
500501
)
501502
try {
502503
val kspOptions = getKspOptions(project)
503504

504-
log.info("SourcesProcessKotlin Project:${projectDir.name}:${src} KtClassCaches:${kotlinImmutableKtClassCache.size} KSPOptions:${kspOptions}")
505+
log.info("SourcesProcessKotlin Project:${projectDir.name}:${src} KSPOptions:${kspOptions}")
505506

506507
val option = createKspOption(
507508
kspOptions,
@@ -522,18 +523,14 @@ object JimmerBuddy {
522523
log.error(e)
523524
}
524525
}
525-
kotlinImmutableKtClassCache.addAll(ktClassCaches)
526526
}
527527
asyncRefreshSources(needRefresh)
528528
}
529529

530530
suspend fun dtoProcessKotlin(projects: Set<GenerateProject>) {
531531
val needRefresh = mutableListOf<Pair<Source, Path>>()
532532
project.runReadActionSmart {
533-
val (resolver, environment, sources) = project.ktClassToKsp(
534-
CopyOnWriteArraySet(),
535-
kotlinImmutableKtClassCache
536-
)
533+
val (resolver, environment, sources) = project.ktClassesToKsp(emptySet())
537534
projects.forEach { (projectDir, sourceFiles, src) ->
538535
sourceFiles.isEmpty() && return@forEach
539536

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2025 Enaium
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+
17+
package cn.enaium.jimmer.buddy.action
18+
19+
import cn.enaium.jimmer.buddy.JimmerBuddy
20+
import cn.enaium.jimmer.buddy.JimmerBuddy.GenerateProject
21+
import cn.enaium.jimmer.buddy.extensions.dto.psi.DtoPsiFile
22+
import cn.enaium.jimmer.buddy.storage.JimmerBuddySetting
23+
import cn.enaium.jimmer.buddy.utility.*
24+
import com.intellij.openapi.actionSystem.ActionUpdateThread
25+
import com.intellij.openapi.actionSystem.AnAction
26+
import com.intellij.openapi.actionSystem.AnActionEvent
27+
import com.intellij.openapi.actionSystem.CommonDataKeys
28+
import com.intellij.psi.PsiClass
29+
import kotlinx.coroutines.CoroutineScope
30+
import kotlinx.coroutines.Dispatchers
31+
import kotlinx.coroutines.launch
32+
import org.jetbrains.kotlin.idea.core.util.toPsiFile
33+
import org.jetbrains.kotlin.psi.KtClass
34+
import org.jetbrains.kotlin.psi.psiUtil.getChildOfType
35+
import kotlin.io.path.extension
36+
37+
/**
38+
* @author Enaium
39+
*/
40+
class Generate : AnAction() {
41+
override fun actionPerformed(e: AnActionEvent) {
42+
val project = e.project ?: return
43+
if (project.isDumb()) return
44+
val dataContext = e.dataContext
45+
dataContext.getData(CommonDataKeys.VIRTUAL_FILE)?.also { file ->
46+
47+
val path = try {
48+
file.toNioPath()
49+
} catch (_: Throwable) {
50+
return
51+
}
52+
CoroutineScope(Dispatchers.IO).launch {
53+
when (path.extension) {
54+
"java" -> {
55+
JimmerBuddy.getWorkspace(project).also {
56+
if (runReadOnly {
57+
file.toPsiFile(project)?.getChildOfType<PsiClass>()?.hasJimmerAnnotation()
58+
} == true) {
59+
it.sourcesProcessJava(
60+
GenerateProject.generate(
61+
path,
62+
GenerateProject.SourceRootType.JAVA
63+
)
64+
)
65+
}
66+
}
67+
}
68+
69+
"kt" -> {
70+
JimmerBuddy.getWorkspace(project).also {
71+
if (runReadOnly {
72+
file.toPsiFile(project)?.getChildOfType<KtClass>()?.hasJimmerAnnotation()
73+
} == true) {
74+
it.sourcesProcessKotlin(
75+
GenerateProject.generate(
76+
path,
77+
listOf(GenerateProject.SourceRootType.KOTLIN) +
78+
if (project.isAndroidProject()) {
79+
listOf(
80+
GenerateProject.SourceRootType.JAVA_KOTLIN,
81+
GenerateProject.SourceRootType.JVM_MAIN_KOTLIN,
82+
GenerateProject.SourceRootType.ANDROID_MAIN_KOTLIN
83+
)
84+
} else {
85+
emptyList()
86+
}
87+
)
88+
)
89+
}
90+
}
91+
}
92+
93+
"dto" -> {
94+
JimmerBuddy.getWorkspace(project).also {
95+
if (project.isJavaProject()) {
96+
it.dtoProcessJava(
97+
GenerateProject.generate(
98+
path,
99+
GenerateProject.SourceRootType.DTO
100+
)
101+
)
102+
} else if (project.isKotlinProject()) {
103+
it.dtoProcessKotlin(
104+
GenerateProject.generate(
105+
path,
106+
GenerateProject.SourceRootType.DTO
107+
)
108+
)
109+
}
110+
}
111+
}
112+
}
113+
}
114+
}
115+
}
116+
117+
override fun update(e: AnActionEvent) {
118+
val project = e.project ?: return
119+
e.visibleWithImmutable()
120+
if (!e.presentation.isVisible) {
121+
e.presentation.isVisible =
122+
e.dataContext.getData(CommonDataKeys.VIRTUAL_FILE)?.toPsiFile(project) is DtoPsiFile
123+
}
124+
e.presentation.isEnabledAndVisible = !JimmerBuddySetting.INSTANCE.state.autoGenerate
125+
}
126+
127+
override fun getActionUpdateThread(): ActionUpdateThread {
128+
return ActionUpdateThread.BGT
129+
}
130+
}

core/src/main/kotlin/cn/enaium/jimmer/buddy/extensions/BuddyPsiTreeChange.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package cn.enaium.jimmer.buddy.extensions
1818

1919
import cn.enaium.jimmer.buddy.JimmerBuddy
2020
import cn.enaium.jimmer.buddy.JimmerBuddy.GenerateProject
21+
import cn.enaium.jimmer.buddy.storage.JimmerBuddySetting
2122
import cn.enaium.jimmer.buddy.utility.*
2223
import com.intellij.openapi.project.Project
2324
import com.intellij.psi.PsiClass
@@ -57,6 +58,9 @@ class BuddyPsiTreeChange(val project: Project) : PsiTreeChangeAdapter() {
5758
}
5859

5960
private fun onChange(psiFile: PsiFile) {
61+
if (!JimmerBuddySetting.INSTANCE.state.autoGenerate) {
62+
return
63+
}
6064
val path = try {
6165
psiFile.virtualFile.toNioPath()
6266
} catch (_: Throwable) {
@@ -67,7 +71,6 @@ class BuddyPsiTreeChange(val project: Project) : PsiTreeChangeAdapter() {
6771
JimmerBuddy.DEQ.schedule("PsiChange") {
6872
if (project.isJavaProject() && !project.isDumb()) {
6973
JimmerBuddy.getWorkspace(project).also {
70-
it.init()
7174
if (path.extension == "java" && runReadOnly {
7275
psiFile.getChildOfType<PsiClass>()?.hasJimmerAnnotation()
7376
} == true) {
@@ -88,7 +91,6 @@ class BuddyPsiTreeChange(val project: Project) : PsiTreeChangeAdapter() {
8891
}
8992
} else if (project.isKotlinProject() && !project.isDumb()) {
9093
JimmerBuddy.getWorkspace(project).also {
91-
it.init()
9294
if (path.extension == "kt" && runReadOnly {
9395
psiFile.getChildOfType<KtClass>()?.hasJimmerAnnotation()
9496
} == true) {

0 commit comments

Comments
 (0)