Skip to content

Commit afb7c24

Browse files
committed
feat: add gutter icon for recursive calls
Fixes #70
1 parent 7037322 commit afb7c24

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package org.tonstudio.tact.ide.highlight
2+
3+
import com.intellij.codeInsight.daemon.LineMarkerInfo
4+
import com.intellij.codeInsight.daemon.LineMarkerProvider
5+
import com.intellij.icons.AllIcons
6+
import com.intellij.openapi.editor.markup.GutterIconRenderer
7+
import com.intellij.psi.PsiDocumentManager
8+
import com.intellij.psi.PsiElement
9+
import com.intellij.psi.util.parentOfType
10+
import com.intellij.util.FunctionUtil
11+
import org.tonstudio.tact.lang.psi.TactCallExpr
12+
import org.tonstudio.tact.lang.psi.TactFunctionOrMethodDeclaration
13+
import org.tonstudio.tact.lang.psi.TactReferenceExpression
14+
15+
class TactRecursiveCallMarkerProvider : LineMarkerProvider {
16+
override fun getLineMarkerInfo(element: PsiElement) = null
17+
18+
override fun collectSlowLineMarkers(elements: List<PsiElement>, result: MutableCollection<in LineMarkerInfo<*>?>) {
19+
val lines = mutableSetOf<Int>()
20+
for (element in elements) {
21+
if (element !is TactCallExpr) continue
22+
23+
val resolve = (element.expression as? TactReferenceExpression)?.resolve() as? TactFunctionOrMethodDeclaration ?: continue
24+
25+
if (isRecursiveCall(element, resolve)) {
26+
val document = PsiDocumentManager.getInstance(element.project).getDocument(element.containingFile) ?: continue
27+
val lineNumber = document.getLineNumber(element.textOffset)
28+
if (!lines.contains(lineNumber)) {
29+
result.add(RecursiveMethodCallMarkerInfo(element.identifier ?: element))
30+
}
31+
32+
lines.add(lineNumber)
33+
}
34+
}
35+
}
36+
37+
private class RecursiveMethodCallMarkerInfo(methodCall: PsiElement) : LineMarkerInfo<PsiElement?>(
38+
methodCall,
39+
methodCall.textRange,
40+
AllIcons.Gutter.RecursiveMethod,
41+
FunctionUtil.constant("Recursive call"),
42+
null,
43+
GutterIconRenderer.Alignment.RIGHT,
44+
{ "Recursive call" }
45+
)
46+
47+
private fun isRecursiveCall(element: PsiElement, function: TactFunctionOrMethodDeclaration): Boolean {
48+
return element.parentOfType<TactFunctionOrMethodDeclaration>() == function
49+
}
50+
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ Provides official support for <a href="https://tact-lang.org/">Tact</a> programm
134134
<codeInsight.typeInfo language="tact" implementationClass="org.tonstudio.tact.ide.codeInsight.TactTypeInfoProvider"/>
135135
<codeInsight.parameterInfo language="tact"
136136
implementationClass="org.tonstudio.tact.ide.codeInsight.TactParameterInfoHandler"/>
137+
<codeInsight.lineMarkerProvider language="tact"
138+
implementationClass="org.tonstudio.tact.ide.highlight.TactRecursiveCallMarkerProvider"/>
137139
<!-- endregion Code Insight -->
138140

139141
<!-- region Documentation -->

0 commit comments

Comments
 (0)