Skip to content

Commit d65fc0a

Browse files
committed
feat: highlight exit points when cursor on fun or receive/external/bounced/init
Fixes #71
1 parent afb7c24 commit d65fc0a

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package org.tonstudio.tact.ide.highlight.exitpoint
2+
3+
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase
4+
import com.intellij.openapi.editor.Editor
5+
import com.intellij.psi.PsiElement
6+
import com.intellij.psi.PsiFile
7+
import com.intellij.psi.util.parentOfTypes
8+
import com.intellij.util.Consumer
9+
import org.tonstudio.tact.lang.psi.*
10+
11+
class TactFunctionExitPointHandler(
12+
editor: Editor,
13+
file: PsiFile,
14+
private val target: PsiElement,
15+
private val function: TactTypeOwner,
16+
) : HighlightUsagesHandlerBase<PsiElement>(editor, file) {
17+
18+
override fun getTargets() = listOf(target)
19+
20+
override fun selectTargets(targets: List<PsiElement>, selectionConsumer: Consumer<in MutableList<out PsiElement>?>) {
21+
selectionConsumer.consume(targets.toMutableList())
22+
}
23+
24+
override fun computeUsages(targets: List<PsiElement>) {
25+
if (function is TactFunctionOrMethodDeclaration) {
26+
val identifier = function.getIdentifier()
27+
if (identifier != null) {
28+
addOccurrence(identifier)
29+
}
30+
}
31+
32+
if (function is TactMessageFunctionDeclaration) {
33+
val identifier = function.getIdentifier()
34+
if (identifier != null) {
35+
addOccurrence(identifier)
36+
}
37+
}
38+
39+
val visitor = object : TactRecursiveElementVisitor() {
40+
override fun visitReturnStatement(expr: TactReturnStatement) {
41+
addOccurrence(expr)
42+
}
43+
44+
override fun visitCallExpr(o: TactCallExpr) {
45+
val callerName = o.expression?.text
46+
if (callerName == "throw") {
47+
addOccurrence(o)
48+
}
49+
}
50+
51+
override fun visitAssertNotNullExpr(o: TactAssertNotNullExpr) {
52+
addOccurrence(o.assertOp)
53+
}
54+
}
55+
56+
visitor.visitTypeOwner(function)
57+
}
58+
59+
companion object {
60+
fun createForElement(editor: Editor, file: PsiFile, element: PsiElement): TactFunctionExitPointHandler? {
61+
val function = element.parentOfTypes(
62+
TactFunctionOrMethodDeclaration::class,
63+
TactMessageFunctionDeclaration::class,
64+
TactContractInitDeclaration::class
65+
)
66+
return function?.let { TactFunctionExitPointHandler(editor, file, element, it) }
67+
}
68+
}
69+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package org.tonstudio.tact.ide.highlight.exitpoint
2+
3+
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerBase
4+
import com.intellij.codeInsight.highlighting.HighlightUsagesHandlerFactoryBase
5+
import com.intellij.openapi.editor.Editor
6+
import com.intellij.psi.PsiElement
7+
import com.intellij.psi.PsiFile
8+
import com.intellij.psi.impl.source.tree.LeafPsiElement
9+
import com.intellij.psi.util.PsiTreeUtil
10+
import com.intellij.psi.util.elementType
11+
import org.tonstudio.tact.lang.TactTypes
12+
import org.tonstudio.tact.lang.psi.TactAssertNotNullExpr
13+
import org.tonstudio.tact.lang.psi.TactContractInitDeclaration
14+
15+
class TactHighlightExitPointsHandlerFactory : HighlightUsagesHandlerFactoryBase() {
16+
override fun createHighlightUsagesHandler(editor: Editor, file: PsiFile, target: PsiElement): HighlightUsagesHandlerBase<*>? {
17+
if (target !is LeafPsiElement) return null
18+
19+
val prevToken = PsiTreeUtil.prevLeaf(target) ?: return null
20+
return createHandler(editor, file, target) ?: createHandler(editor, file, prevToken)
21+
}
22+
23+
private fun createHandler(editor: Editor, file: PsiFile, target: PsiElement): HighlightUsagesHandlerBase<*>? {
24+
val elementType = target.elementType
25+
26+
if (
27+
elementType == TactTypes.IDENTIFIER &&
28+
target.parent is TactContractInitDeclaration &&
29+
target.textMatches("init")
30+
) {
31+
return TactFunctionExitPointHandler.createForElement(editor, file, target)
32+
}
33+
34+
if (
35+
elementType == TactTypes.RETURN ||
36+
elementType == TactTypes.FUN ||
37+
elementType == TactTypes.RECEIVE ||
38+
elementType == TactTypes.EXTERNAL ||
39+
elementType == TactTypes.BOUNCED
40+
) {
41+
return TactFunctionExitPointHandler.createForElement(editor, file, target)
42+
}
43+
44+
if (elementType == TactTypes.ASSERT_OP) {
45+
if (target.parent is TactAssertNotNullExpr) {
46+
return TactFunctionExitPointHandler.createForElement(editor, file, target)
47+
}
48+
}
49+
50+
return null
51+
}
52+
53+
}

src/main/resources/META-INF/plugin.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ Provides official support for <a href="https://tact-lang.org/">Tact</a> programm
136136
implementationClass="org.tonstudio.tact.ide.codeInsight.TactParameterInfoHandler"/>
137137
<codeInsight.lineMarkerProvider language="tact"
138138
implementationClass="org.tonstudio.tact.ide.highlight.TactRecursiveCallMarkerProvider"/>
139+
<highlightUsagesHandlerFactory
140+
implementation="org.tonstudio.tact.ide.highlight.exitpoint.TactHighlightExitPointsHandlerFactory"/>
139141
<!-- endregion Code Insight -->
140142

141143
<!-- region Documentation -->

0 commit comments

Comments
 (0)