Skip to content

Commit 8e2a696

Browse files
committed
fix(lsp/java/actions): Handle no fields found and dismiss on action
This commit addresses two issues in the Java LSP actions: 1. **Handles the case where no fields are found:** Previously, actions like generating constructors, getters/setters, or `toString` methods would throw an exception if no fields were found in the class at the specified range. This commit modifies the `findFields` method to return `null` if no fields are found and the respective generator actions now check for this `null` value. If `null` is returned, an error message is displayed to the user. 2. **Dismisses actions on completion:** The `CommentAction` and `UncommentAction` now dismiss the action dialog upon successful execution by overriding `dismissOnAction` to return `true`. This provides a more streamlined user experience.
1 parent 5b8b60d commit 8e2a696

File tree

6 files changed

+43
-41
lines changed

6 files changed

+43
-41
lines changed

lsp/java/src/main/java/com/itsaky/androidide/lsp/java/actions/FieldBasedAction.kt

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.itsaky.androidide.lsp.java.actions
1919

2020
import android.content.Context
21+
import com.blankj.utilcode.util.ThreadUtils
2122
import com.itsaky.androidide.actions.ActionData
2223
import com.itsaky.androidide.actions.hasRequiredData
2324
import com.itsaky.androidide.actions.markInvisible
@@ -28,6 +29,7 @@ import com.itsaky.androidide.lsp.java.compiler.CompileTask
2829
import com.itsaky.androidide.lsp.java.visitors.FindTypeDeclarationAt
2930
import com.itsaky.androidide.projects.IProjectManager
3031
import com.itsaky.androidide.resources.R
32+
import com.itsaky.androidide.utils.flashError
3133
import com.itsaky.androidide.utils.flashInfo
3234
import io.github.rosemoe.sora.widget.CodeEditor
3335
import jdkx.lang.model.element.Modifier.STATIC
@@ -77,21 +79,21 @@ abstract class FieldBasedAction : BaseJavaCodeAction() {
7779

7880
return JavaCompilerProvider.get(module).compile(file).get { task ->
7981
val triple = findFields(task, file, range)
80-
val type = triple.second
81-
val fields = triple.third
82-
val fieldNames = fields.map { "${it.name}: ${it.type}" } // Get the names
82+
val type = triple?.second
83+
val fields = triple?.third
84+
val fieldNames = fields?.map { "${it.name}: ${it.type}" } // Get the names
8385

84-
log.debug("Found {} fields in class {}", fieldNames.size, type.simpleName)
86+
log.debug("Found {} fields in class {}", fieldNames?.size, type?.simpleName)
8587

86-
return@get fieldNames
88+
return@get fieldNames ?: emptyList<String>()
8789
}
8890
}
8991

9092
protected fun findFields(
9193
task: CompileTask,
9294
file: Path,
9395
range: com.itsaky.androidide.models.Range
94-
): Triple<FindTypeDeclarationAt, ClassTree, MutableList<VariableTree>> {
96+
): Triple<FindTypeDeclarationAt, ClassTree, MutableList<VariableTree>>? {
9597
// 1-based line and column index
9698
val startLine = range.start.line + 1
9799
val startColumn = range.start.column + 1
@@ -114,9 +116,7 @@ abstract class FieldBasedAction : BaseJavaCodeAction() {
114116
}
115117

116118
if (type == null) {
117-
throw CompletionException(
118-
RuntimeException("Unable to find class declaration within cursor range")
119-
)
119+
return null
120120
}
121121

122122
val fields =
@@ -128,6 +128,25 @@ abstract class FieldBasedAction : BaseJavaCodeAction() {
128128
return Triple(typeFinder, type, fields)
129129
}
130130

131+
protected inline fun withValidFields(
132+
data: ActionData,
133+
task: CompileTask,
134+
file: Path,
135+
range: com.itsaky.androidide.models.Range,
136+
onValid: (FindTypeDeclarationAt, ClassTree, MutableList<VariableTree>) -> Unit
137+
) {
138+
val triple = findFields(task, file, range)
139+
if (triple == null) {
140+
ThreadUtils.runOnUiThread {
141+
flashError(data[Context::class.java]!!.getString(R.string.msg_no_fields_found))
142+
}
143+
return
144+
}
145+
146+
val (typeFinder, type, fields) = triple
147+
onValid(typeFinder, type, fields)
148+
}
149+
131150
@Suppress("UNCHECKED_CAST")
132151
override fun postExec(data: ActionData, result: Any) {
133152
if (result !is List<*>) {

lsp/java/src/main/java/com/itsaky/androidide/lsp/java/actions/common/CommentAction.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ class CommentAction : BaseJavaCodeAction() {
4444
return true
4545
}
4646

47-
override fun dismissOnAction() = false
47+
override fun dismissOnAction() = true
4848
}

lsp/java/src/main/java/com/itsaky/androidide/lsp/java/actions/common/UncommentAction.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ class UncommentAction : BaseJavaCodeAction() {
4848
return true
4949
}
5050

51-
override fun dismissOnAction() = false
51+
override fun dismissOnAction() = true
5252
}

lsp/java/src/main/java/com/itsaky/androidide/lsp/java/actions/generators/GenerateConstructorAction.kt

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,16 +87,10 @@ class GenerateConstructorAction : FieldBasedAction() {
8787
val file = data.requirePath()
8888

8989
compiler.compile(file).run { task ->
90-
val triple = findFields(task, file, range)
91-
val typeFinder = triple.first
92-
val type = triple.second
93-
val fields = triple.third
94-
95-
fields.removeIf { !selected.contains("${it.name}: ${it.type}") }
96-
97-
log.debug("Creating toString() method with fields: {}", fields.map { it.name })
98-
99-
generateForFields(data, task, type, fields.map { TreePath(typeFinder.path, it) })
90+
withValidFields(data, task, file, range) { typeFinder, type, fields ->
91+
fields.removeIf { !selected.contains("${it.name}: ${it.type}") }
92+
generateForFields(data, task, type, fields.map { TreePath(typeFinder.path, it) })
93+
}
10094
}
10195
}
10296

lsp/java/src/main/java/com/itsaky/androidide/lsp/java/actions/generators/GenerateSettersAndGettersAction.kt

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,16 +94,10 @@ class GenerateSettersAndGettersAction : FieldBasedAction() {
9494
val file = data.requirePath()
9595

9696
compiler.compile(file).run { task ->
97-
val triple = findFields(task, file, range)
98-
val typeFinder = triple.first
99-
val type = triple.second
100-
val fields = triple.third
101-
102-
fields.removeIf { !names.contains("${it.name}: ${it.type}") }
103-
104-
log.debug("Creating setters/getters for fields: {}", fields.map { it.name })
105-
106-
generateForFields(data, task, type, fields.map { TreePath(typeFinder.path, it) })
97+
withValidFields(data, task, file, range) { typeFinder, type, fields ->
98+
fields.removeIf { !names.contains("${it.name}: ${it.type}") }
99+
generateForFields(data, task, type, fields.map { TreePath(typeFinder.path, it) })
100+
}
107101
}
108102
}
109103

lsp/java/src/main/java/com/itsaky/androidide/lsp/java/actions/generators/GenerateToStringMethodAction.kt

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.itsaky.androidide.actions.requireFile
2727
import com.itsaky.androidide.actions.requirePath
2828
import com.itsaky.androidide.lsp.java.JavaCompilerProvider
2929
import com.itsaky.androidide.lsp.java.actions.FieldBasedAction
30+
import com.itsaky.androidide.lsp.java.actions.generators.GenerateConstructorAction.Companion
3031
import com.itsaky.androidide.lsp.java.compiler.CompileTask
3132
import com.itsaky.androidide.lsp.java.utils.EditHelper
3233
import com.itsaky.androidide.preferences.internal.EditorPreferences
@@ -89,16 +90,10 @@ class GenerateToStringMethodAction : FieldBasedAction() {
8990
val file = data.requirePath()
9091

9192
compiler.compile(file).run { task ->
92-
val triple = findFields(task, file, range)
93-
val typeFinder = triple.first
94-
val type = triple.second
95-
val fields = triple.third
96-
97-
fields.removeIf { !selected.contains("${it.name}: ${it.type}") }
98-
99-
log.debug("Creating toString() method with fields: {}", fields.map { it.name })
100-
101-
generateForFields(data, task, type, fields.map { TreePath(typeFinder.path, it) })
93+
withValidFields(data, task, file, range) { typeFinder, type, fields ->
94+
fields.removeIf { !selected.contains("${it.name}: ${it.type}") }
95+
generateForFields(data, task, type, fields.map { TreePath(typeFinder.path, it) })
96+
}
10297
}
10398
}
10499

0 commit comments

Comments
 (0)