Skip to content

Commit 07d5903

Browse files
authored
ADFA-4867: Point Kotlin code actions at their own tooltip tags (#1582)
1 parent 80fa0df commit 07d5903

11 files changed

Lines changed: 418 additions & 284 deletions

File tree

‎idetooltips/src/main/java/com/itsaky/androidide/idetooltips/TooltipTag.kt‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,15 @@ object TooltipTag {
8080
const val EDITOR_CODE_ACTIONS_GEN_TO_STRING_DIALOG = "editor.codeactions.gentostring.dialog"
8181
const val EDITOR_CODE_ACTIONS_UNUSED_IMPORTS = "editor.codeactions.unusedimports"
8282
const val EDITOR_CODE_ACTIONS_ORGANIZE_IMPORTS = "editor.codeactions.organizeimports"
83-
const val EDITOR_CODE_ACTIONS_KT_FIX_IMPORTS = "editor.codeactions.kotlin.fiximports"
83+
84+
// Kotlin code actions. Tags are per-language even where the action exists in both languages,
85+
// so the tooltip can describe the Kotlin behaviour (see ADFA-4730).
86+
const val EDITOR_CODE_ACTIONS_KT_COMMENT = "editor.codeactions.kotlin.comment"
87+
const val EDITOR_CODE_ACTIONS_KT_UNCOMMENT = "editor.codeactions.kotlin.uncomment"
88+
const val EDITOR_CODE_ACTIONS_KT_IMPORT_CLASS = "editor.codeactions.kotlin.importclass"
89+
const val EDITOR_CODE_ACTIONS_KT_ORGANIZE_IMPORTS = "editor.codeactions.kotlin.organizeimports"
90+
const val EDITOR_CODE_ACTIONS_KT_IMPLEMENT_MEMBERS = "editor.codeactions.kotlin.implementmembers"
91+
const val EDITOR_CODE_ACTIONS_KT_NULL_SAFETY_FIX = "editor.codeactions.kotlin.nullsafetyfix"
8492
const val EDITOR_CODE_ACTIONS_KT_SURROUND_TRY_CATCH = "editor.codeactions.kotlin.trycatch"
8593

8694
const val EXIT_TO_MAIN = "exit.to.main"
Lines changed: 94 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,94 @@
1-
/*
2-
* This file is part of AndroidIDE.
3-
*
4-
* AndroidIDE is free software: you can redistribute it and/or modify
5-
* it under the terms of the GNU General Public License as published by
6-
* the Free Software Foundation, either version 3 of the License, or
7-
* (at your option) any later version.
8-
*
9-
* AndroidIDE is distributed in the hope that it will be useful,
10-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-
* GNU General Public License for more details.
13-
*
14-
* You should have received a copy of the GNU General Public License
15-
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
16-
*/
17-
package com.itsaky.androidide.lsp.actions
18-
19-
import android.content.Context
20-
import android.graphics.drawable.Drawable
21-
import com.itsaky.androidide.actions.ActionData
22-
import com.itsaky.androidide.actions.ActionItem
23-
import com.itsaky.androidide.actions.EditorActionItem
24-
import com.itsaky.androidide.actions.hasRequiredData
25-
import com.itsaky.androidide.actions.markInvisible
26-
import com.itsaky.androidide.actions.requireContext
27-
import com.itsaky.androidide.actions.requireEditor
28-
import com.itsaky.androidide.actions.requireFile
29-
import com.itsaky.androidide.idetooltips.TooltipTag
30-
import com.itsaky.androidide.resources.R
31-
import io.github.rosemoe.sora.text.batchEdit
32-
import java.io.File
33-
34-
/** @author Akash Yadav */
35-
class CommentLineAction(
36-
lang: String,
37-
private val targetFileExtensions: List<String>,
38-
private val lineCommentToken: String,
39-
) : EditorActionItem {
40-
41-
constructor(lang: String, extension: String, lineCommentToken: String) :
42-
this(lang, listOf(extension), lineCommentToken)
43-
override val id: String = "ide.editor.lsp.$lang.commentLine"
44-
override var label: String = ""
45-
46-
override var visible = true
47-
override var enabled = true
48-
override var icon: Drawable? = null
49-
override var location: ActionItem.Location = ActionItem.Location.EDITOR_CODE_ACTIONS
50-
override var requiresUIThread: Boolean = true
51-
override var tooltipTag: String = TooltipTag.EDITOR_CODE_ACTIONS_COMMENT
52-
53-
override fun prepare(data: ActionData) {
54-
super.prepare(data)
55-
56-
if (!data.hasRequiredData(Context::class.java, File::class.java)) {
57-
markInvisible()
58-
return
59-
}
60-
61-
val context = data.requireContext()
62-
label = context.getString(R.string.action_comment_line)
63-
64-
val file = data.requireFile()
65-
if (file.extension !in targetFileExtensions) {
66-
markInvisible()
67-
return
68-
}
69-
}
70-
71-
override suspend fun execAction(data: ActionData): Boolean {
72-
val editor = data.requireEditor()
73-
val text = editor.text
74-
val cursor = editor.cursor
75-
76-
text.batchEdit {
77-
for (line in cursor.leftLine..cursor.rightLine) {
78-
text.insert(line, 0, lineCommentToken)
79-
}
80-
}
81-
82-
return true
83-
}
84-
85-
override fun dismissOnAction() = true
86-
}
1+
/*
2+
* This file is part of AndroidIDE.
3+
*
4+
* AndroidIDE is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* AndroidIDE is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
package com.itsaky.androidide.lsp.actions
18+
19+
import android.content.Context
20+
import android.graphics.drawable.Drawable
21+
import com.itsaky.androidide.actions.ActionData
22+
import com.itsaky.androidide.actions.ActionItem
23+
import com.itsaky.androidide.actions.EditorActionItem
24+
import com.itsaky.androidide.actions.hasRequiredData
25+
import com.itsaky.androidide.actions.markInvisible
26+
import com.itsaky.androidide.actions.requireContext
27+
import com.itsaky.androidide.actions.requireEditor
28+
import com.itsaky.androidide.actions.requireFile
29+
import com.itsaky.androidide.resources.R
30+
import io.github.rosemoe.sora.text.batchEdit
31+
import java.io.File
32+
33+
/** @author Akash Yadav */
34+
class CommentLineAction(
35+
lang: String,
36+
private val targetFileExtensions: List<String>,
37+
private val lineCommentToken: String,
38+
tag: String,
39+
) : EditorActionItem {
40+
companion object {
41+
/** The id is per-language, since one instance is registered per language. */
42+
fun idFor(lang: String) = "ide.editor.lsp.$lang.commentLine"
43+
}
44+
45+
constructor(lang: String, extension: String, lineCommentToken: String, tag: String) :
46+
this(lang, listOf(extension), lineCommentToken, tag)
47+
48+
override val id: String = idFor(lang)
49+
override var label: String = ""
50+
51+
override var visible = true
52+
override var enabled = true
53+
override var icon: Drawable? = null
54+
override var location: ActionItem.Location = ActionItem.Location.EDITOR_CODE_ACTIONS
55+
override var requiresUIThread: Boolean = true
56+
57+
// Required, not defaulted: one instance is registered per language, and a default would let a
58+
// new language silently inherit another language's tooltip.
59+
override var tooltipTag: String = tag
60+
61+
override fun prepare(data: ActionData) {
62+
super.prepare(data)
63+
64+
if (!data.hasRequiredData(Context::class.java, File::class.java)) {
65+
markInvisible()
66+
return
67+
}
68+
69+
val context = data.requireContext()
70+
label = context.getString(R.string.action_comment_line)
71+
72+
val file = data.requireFile()
73+
if (file.extension !in targetFileExtensions) {
74+
markInvisible()
75+
return
76+
}
77+
}
78+
79+
override suspend fun execAction(data: ActionData): Boolean {
80+
val editor = data.requireEditor()
81+
val text = editor.text
82+
val cursor = editor.cursor
83+
84+
text.batchEdit {
85+
for (line in cursor.leftLine..cursor.rightLine) {
86+
text.insert(line, 0, lineCommentToken)
87+
}
88+
}
89+
90+
return true
91+
}
92+
93+
override fun dismissOnAction() = true
94+
}
Lines changed: 98 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,98 @@
1-
/*
2-
* This file is part of AndroidIDE.
3-
*
4-
* AndroidIDE is free software: you can redistribute it and/or modify
5-
* it under the terms of the GNU General Public License as published by
6-
* the Free Software Foundation, either version 3 of the License, or
7-
* (at your option) any later version.
8-
*
9-
* AndroidIDE is distributed in the hope that it will be useful,
10-
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11-
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-
* GNU General Public License for more details.
13-
*
14-
* You should have received a copy of the GNU General Public License
15-
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
16-
*/
17-
package com.itsaky.androidide.lsp.actions
18-
19-
import android.content.Context
20-
import android.graphics.drawable.Drawable
21-
import com.itsaky.androidide.actions.ActionData
22-
import com.itsaky.androidide.actions.ActionItem
23-
import com.itsaky.androidide.actions.EditorActionItem
24-
import com.itsaky.androidide.actions.hasRequiredData
25-
import com.itsaky.androidide.actions.markInvisible
26-
import com.itsaky.androidide.actions.requireContext
27-
import com.itsaky.androidide.actions.requireEditor
28-
import com.itsaky.androidide.actions.requireFile
29-
import com.itsaky.androidide.idetooltips.TooltipTag
30-
import com.itsaky.androidide.resources.R
31-
import io.github.rosemoe.sora.text.batchEdit
32-
import java.io.File
33-
34-
/** @author Akash Yadav */
35-
class UncommentLineAction(
36-
lang: String,
37-
private val targetFileExtensions: List<String>,
38-
private val lineCommentToken: String,
39-
) : EditorActionItem {
40-
41-
constructor(lang: String, extension: String, lineCommentToken: String) :
42-
this(lang, listOf(extension), lineCommentToken)
43-
44-
override val id: String = "ide.editor.lsp.$lang.uncommentLine"
45-
override var label: String = ""
46-
47-
override var visible = true
48-
override var enabled = true
49-
override var icon: Drawable? = null
50-
override var location: ActionItem.Location = ActionItem.Location.EDITOR_CODE_ACTIONS
51-
override var requiresUIThread: Boolean = true
52-
override var tooltipTag: String = TooltipTag.EDITOR_CODE_ACTIONS_UNCOMMENT
53-
54-
55-
override fun prepare(data: ActionData) {
56-
super.prepare(data)
57-
58-
if (!data.hasRequiredData(Context::class.java, File::class.java)) {
59-
markInvisible()
60-
return
61-
}
62-
63-
val context = data.requireContext()
64-
label = context.getString(R.string.action_uncomment_line)
65-
66-
val file = data.requireFile()
67-
if (file.extension !in targetFileExtensions) {
68-
markInvisible()
69-
return
70-
}
71-
}
72-
73-
override suspend fun execAction(data: ActionData): Boolean {
74-
val editor = data.requireEditor()
75-
val text = editor.text
76-
val cursor = editor.cursor
77-
78-
text.batchEdit {
79-
for (line in cursor.leftLine..cursor.rightLine) {
80-
val l = text.getLineString(line)
81-
if (l.trim().startsWith(lineCommentToken)) {
82-
val i = l.indexOf(lineCommentToken)
83-
text.delete(line, i, line, i + 2)
84-
}
85-
}
86-
}
87-
88-
return true
89-
}
90-
91-
override fun dismissOnAction() = true
92-
}
1+
/*
2+
* This file is part of AndroidIDE.
3+
*
4+
* AndroidIDE is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* AndroidIDE is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
16+
*/
17+
package com.itsaky.androidide.lsp.actions
18+
19+
import android.content.Context
20+
import android.graphics.drawable.Drawable
21+
import com.itsaky.androidide.actions.ActionData
22+
import com.itsaky.androidide.actions.ActionItem
23+
import com.itsaky.androidide.actions.EditorActionItem
24+
import com.itsaky.androidide.actions.hasRequiredData
25+
import com.itsaky.androidide.actions.markInvisible
26+
import com.itsaky.androidide.actions.requireContext
27+
import com.itsaky.androidide.actions.requireEditor
28+
import com.itsaky.androidide.actions.requireFile
29+
import com.itsaky.androidide.resources.R
30+
import io.github.rosemoe.sora.text.batchEdit
31+
import java.io.File
32+
33+
/** @author Akash Yadav */
34+
class UncommentLineAction(
35+
lang: String,
36+
private val targetFileExtensions: List<String>,
37+
private val lineCommentToken: String,
38+
tag: String,
39+
) : EditorActionItem {
40+
companion object {
41+
/** The id is per-language, since one instance is registered per language. */
42+
fun idFor(lang: String) = "ide.editor.lsp.$lang.uncommentLine"
43+
}
44+
45+
constructor(lang: String, extension: String, lineCommentToken: String, tag: String) :
46+
this(lang, listOf(extension), lineCommentToken, tag)
47+
48+
override val id: String = idFor(lang)
49+
override var label: String = ""
50+
51+
override var visible = true
52+
override var enabled = true
53+
override var icon: Drawable? = null
54+
override var location: ActionItem.Location = ActionItem.Location.EDITOR_CODE_ACTIONS
55+
override var requiresUIThread: Boolean = true
56+
57+
// Required, not defaulted: one instance is registered per language, and a default would let a
58+
// new language silently inherit another language's tooltip.
59+
override var tooltipTag: String = tag
60+
61+
override fun prepare(data: ActionData) {
62+
super.prepare(data)
63+
64+
if (!data.hasRequiredData(Context::class.java, File::class.java)) {
65+
markInvisible()
66+
return
67+
}
68+
69+
val context = data.requireContext()
70+
label = context.getString(R.string.action_uncomment_line)
71+
72+
val file = data.requireFile()
73+
if (file.extension !in targetFileExtensions) {
74+
markInvisible()
75+
return
76+
}
77+
}
78+
79+
override suspend fun execAction(data: ActionData): Boolean {
80+
val editor = data.requireEditor()
81+
val text = editor.text
82+
val cursor = editor.cursor
83+
84+
text.batchEdit {
85+
for (line in cursor.leftLine..cursor.rightLine) {
86+
val l = text.getLineString(line)
87+
if (l.trim().startsWith(lineCommentToken)) {
88+
val i = l.indexOf(lineCommentToken)
89+
text.delete(line, i, line, i + 2)
90+
}
91+
}
92+
}
93+
94+
return true
95+
}
96+
97+
override fun dismissOnAction() = true
98+
}

0 commit comments

Comments
 (0)