diff --git a/commander b/commander index 8332f7432..07c226757 160000 --- a/commander +++ b/commander @@ -1 +1 @@ -Subproject commit 8332f743299d9357834ffc5f9b491a2562cfc2ae +Subproject commit 07c22675706c52a973a9eb0f78bbbafc4f71b74f diff --git a/core/src/main/kotlin/spp/jetbrains/command/LiveLocationContext.kt b/core/src/main/kotlin/spp/jetbrains/command/LiveLocationContext.kt index 1414343b6..0872cad83 100644 --- a/core/src/main/kotlin/spp/jetbrains/command/LiveLocationContext.kt +++ b/core/src/main/kotlin/spp/jetbrains/command/LiveLocationContext.kt @@ -21,7 +21,6 @@ import spp.jetbrains.marker.source.SourceFileMarker import spp.protocol.artifact.ArtifactQualifiedName data class LiveLocationContext( - val lineNumber: Int, val qualifiedName: ArtifactQualifiedName, val fileMarker: SourceFileMarker, val element: PsiElement, diff --git a/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/JavascriptLineMarkerProvider.kt b/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/JavascriptLineMarkerProvider.kt index 26f8e7b29..3243e392c 100644 --- a/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/JavascriptLineMarkerProvider.kt +++ b/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/JavascriptLineMarkerProvider.kt @@ -19,7 +19,6 @@ package spp.jetbrains.marker.js import com.intellij.codeInsight.daemon.LineMarkerInfo import com.intellij.lang.javascript.psi.JSFile import com.intellij.psi.PsiElement -import spp.jetbrains.marker.SourceMarker import spp.jetbrains.marker.plugin.SourceLineMarkerProvider import spp.jetbrains.marker.source.SourceFileMarker import spp.jetbrains.marker.source.mark.gutter.GutterMark @@ -40,7 +39,6 @@ class JavascriptLineMarkerProvider : SourceLineMarkerProvider() { } override fun getLineMarkerInfo(parent: PsiElement?, element: PsiElement): LineMarkerInfo? { - val fileMarker = SourceMarker.getInstance(element.project).getSourceFileMarker(element.containingFile) return null //todo: this } diff --git a/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/service/JavascriptArtifactCreationService.kt b/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/service/JavascriptArtifactCreationService.kt index cf25ba58e..4a27b4000 100644 --- a/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/service/JavascriptArtifactCreationService.kt +++ b/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/service/JavascriptArtifactCreationService.kt @@ -84,12 +84,8 @@ class JavascriptArtifactCreationService : IArtifactCreationService { SourceMark.Type.GUTTER ) as ExpressionGutterMark return if (autoApply) { - if (gutterMark.canApply()) { - gutterMark.apply(true) - gutterMark - } else { - null - } + gutterMark.apply(true) + gutterMark } else { gutterMark } @@ -151,12 +147,8 @@ class JavascriptArtifactCreationService : IArtifactCreationService { SourceMark.Type.INLAY ) as ExpressionInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - error("Could not apply inlay mark: $inlayMark") - } + inlayMark.apply(true) + inlayMark } else { inlayMark } @@ -188,12 +180,8 @@ class JavascriptArtifactCreationService : IArtifactCreationService { SourceMark.Type.INLAY ) as ExpressionInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - null - } + inlayMark.apply(true) + inlayMark } else { inlayMark } diff --git a/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/service/JavascriptArtifactNamingService.kt b/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/service/JavascriptArtifactNamingService.kt index 643aa5fe5..a904a1629 100644 --- a/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/service/JavascriptArtifactNamingService.kt +++ b/marker/js-marker/src/main/kotlin/spp/jetbrains/marker/js/service/JavascriptArtifactNamingService.kt @@ -79,15 +79,18 @@ class JavascriptArtifactNamingService : IArtifactNamingService { override fun getFullyQualifiedName(element: PsiElement): ArtifactQualifiedName { return when (element) { - is JSClass -> { - ArtifactQualifiedName(element.qualifiedName!!, null, ArtifactType.CLASS) - } + is JSClass -> ArtifactQualifiedName( + element.qualifiedName!!, + type = ArtifactType.CLASS, + lineNumber = SourceMarkerUtils.getLineNumber(element) + ) is JSFunctionExpression -> getStatementOrExpressionQualifiedName(element, ArtifactType.EXPRESSION) - - is JSFunction -> { - ArtifactQualifiedName(element.qualifiedName!!, null, ArtifactType.METHOD) - } + is JSFunction -> ArtifactQualifiedName( + element.qualifiedName!!, + type = ArtifactType.METHOD, + lineNumber = SourceMarkerUtils.getLineNumber(element) + ) is JSStatement, is JSStatementList -> getStatementOrExpressionQualifiedName(element, ArtifactType.STATEMENT) else -> getStatementOrExpressionQualifiedName(element, ArtifactType.EXPRESSION) @@ -104,12 +107,14 @@ class JavascriptArtifactNamingService : IArtifactNamingService { val parentElement = element.parentOfType() return if (parentElement != null) { ArtifactQualifiedName( - "${getFullyQualifiedName(parentElement).identifier}.${name}", null, type, + "${getFullyQualifiedName(parentElement).identifier}.${name}", + type = type, lineNumber = SourceMarkerUtils.getLineNumber(element) ) } else { ArtifactQualifiedName( - "${element.containingFile.virtualFile.path}#$name", null, type, + "${element.containingFile.virtualFile.path}#$name", + type = type, lineNumber = SourceMarkerUtils.getLineNumber(element) ) } @@ -120,7 +125,13 @@ class JavascriptArtifactNamingService : IArtifactNamingService { psiFile.acceptChildren(object : JSRecursiveWalkingElementVisitor() { override fun visitJSClass(node: JSClass) { // TODO: check this also works for typescript classes, otherwise use visitTypescriptClass super.visitJSClass(node) - classQualifiedNames.add(ArtifactQualifiedName(node.qualifiedName!!, type = ArtifactType.CLASS)) + classQualifiedNames.add( + ArtifactQualifiedName( + node.qualifiedName!!, + type = ArtifactType.CLASS, + lineNumber = SourceMarkerUtils.getLineNumber(node) + ) + ) } }) return classQualifiedNames diff --git a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/JVMLineMarkerProvider.kt b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/JVMLineMarkerProvider.kt index d15838001..92037eb16 100644 --- a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/JVMLineMarkerProvider.kt +++ b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/JVMLineMarkerProvider.kt @@ -18,7 +18,6 @@ package spp.jetbrains.marker.jvm import com.intellij.codeInsight.daemon.GutterIconNavigationHandler import com.intellij.codeInsight.daemon.LineMarkerInfo -import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.editor.markup.GutterIconRenderer import com.intellij.psi.PsiClass import com.intellij.psi.PsiElement @@ -27,13 +26,11 @@ import com.intellij.psi.PsiJavaFile import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.plugins.groovy.lang.psi.GroovyFile import org.jetbrains.uast.UClass -import org.jetbrains.uast.UMethod import org.jetbrains.uast.toUElement -import org.jetbrains.uast.toUElementOfType import spp.jetbrains.marker.SourceMarker import spp.jetbrains.marker.impl.ArtifactCreationService -import spp.jetbrains.marker.plugin.SourceLineMarkerProvider import spp.jetbrains.marker.jvm.service.utils.JVMMarkerUtils +import spp.jetbrains.marker.plugin.SourceLineMarkerProvider import spp.jetbrains.marker.source.SourceFileMarker.Companion.SUPPORTED_FILE_TYPES import spp.jetbrains.marker.source.mark.api.SourceMark import spp.jetbrains.marker.source.mark.api.key.SourceKey @@ -49,10 +46,6 @@ import spp.jetbrains.marker.source.mark.gutter.MethodGutterMark */ abstract class JVMLineMarkerProvider : SourceLineMarkerProvider() { - companion object { - private val log = logger() - } - override fun getLineMarkerInfo( parent: PsiElement?, element: PsiElement @@ -65,9 +58,8 @@ abstract class JVMLineMarkerProvider : SourceLineMarkerProvider() { } private fun getClassGutterMark(element: PsiIdentifier): LineMarkerInfo? { - val fileMarker = SourceMarker.getInstance(element.project).getSourceFileMarker(element.containingFile) ?: return null + val fileMarker = SourceMarker.getSourceFileMarker(element.containingFile) ?: return null val artifactQualifiedName = JVMMarkerUtils.getFullyQualifiedName(element.parent.toUElement() as UClass) - if (!SourceMarker.getInstance(element.project).configuration.createSourceMarkFilter.test(artifactQualifiedName)) return null //check by artifact name first due to user can erroneously name same class twice var gutterMark = fileMarker.getSourceMark(artifactQualifiedName, SourceMark.Type.GUTTER) as ClassGutterMark? @@ -95,14 +87,8 @@ abstract class JVMLineMarkerProvider : SourceLineMarkerProvider() { } private fun getMethodGutterMark(element: PsiElement): LineMarkerInfo? { - val fileMarker = SourceMarker.getInstance(element.project).getSourceFileMarker(element.containingFile) ?: return null - val uMethod = element.parent.toUElementOfType() - if (uMethod == null) { - log.warn("Unable to transform to UMethod: ${element.parent}") - return null - } - val artifactQualifiedName = JVMMarkerUtils.getFullyQualifiedName(uMethod) - if (!SourceMarker.getInstance(element.project).configuration.createSourceMarkFilter.test(artifactQualifiedName)) return null + val fileMarker = SourceMarker.getSourceFileMarker(element.containingFile) ?: return null + val artifactQualifiedName = JVMMarkerUtils.getFullyQualifiedName(element) //check by artifact name first due to user can erroneously name same method twice var gutterMark = fileMarker.getSourceMark( diff --git a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/JVMSourceInlayHintProvider.kt b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/JVMSourceInlayHintProvider.kt index a6127405c..90d2da3e3 100644 --- a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/JVMSourceInlayHintProvider.kt +++ b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/JVMSourceInlayHintProvider.kt @@ -22,12 +22,9 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.psi.PsiMethodCallExpression import com.intellij.psi.PsiStatement -import org.jetbrains.uast.UExpression -import org.jetbrains.uast.UMethod -import org.jetbrains.uast.toUElement import spp.jetbrains.marker.SourceMarker -import spp.jetbrains.marker.plugin.SourceInlayHintProvider import spp.jetbrains.marker.jvm.service.utils.JVMMarkerUtils +import spp.jetbrains.marker.plugin.SourceInlayHintProvider import spp.jetbrains.marker.source.mark.inlay.InlayMark import spp.jetbrains.marker.source.mark.inlay.config.InlayMarkVirtualText @@ -44,19 +41,11 @@ class JVMSourceInlayHintProvider : SourceInlayHintProvider() { if ((parent is PsiMethod && element === parent.nameIdentifier) || (JVMMarkerUtils.getNameIdentifier(parent) === element) ) { - val fileMarker = SourceMarker.getInstance(element.project).getSourceFileMarker(element.containingFile)!! - val artifactQualifiedName = JVMMarkerUtils.getFullyQualifiedName(parent.toUElement() as UMethod) - return if (!SourceMarker.getInstance(element.project).configuration.createSourceMarkFilter.test(artifactQualifiedName)) null else { - JVMMarkerUtils.getOrCreateMethodInlayMark(fileMarker, element) - } + val fileMarker = SourceMarker.getSourceFileMarker(element.containingFile)!! + return JVMMarkerUtils.getOrCreateMethodInlayMark(fileMarker, element) } else if (element is PsiStatement) { - val fileMarker = SourceMarker.getInstance(element.project).getSourceFileMarker(element.containingFile)!! - val artifactQualifiedName = JVMMarkerUtils.getFullyQualifiedName( - JVMMarkerUtils.getUniversalExpression(element).toUElement() as UExpression - ) - return if (!SourceMarker.getInstance(element.project).configuration.createSourceMarkFilter.test(artifactQualifiedName)) null else { - JVMMarkerUtils.getOrCreateExpressionInlayMark(fileMarker, element) - } + val fileMarker = SourceMarker.getSourceFileMarker(element.containingFile)!! + return JVMMarkerUtils.getOrCreateExpressionInlayMark(fileMarker, element) } return null } diff --git a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactCreationService.kt b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactCreationService.kt index 8f077e47e..7015da9c6 100644 --- a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactCreationService.kt +++ b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactCreationService.kt @@ -73,12 +73,8 @@ class JVMArtifactCreationService : IArtifactCreationService { SourceMark.Type.GUTTER ) as MethodGutterMark return if (autoApply) { - if (gutterMark.canApply()) { - gutterMark.apply(true) - gutterMark - } else { - null - } + gutterMark.apply(true) + gutterMark } else { gutterMark } diff --git a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactNamingService.kt b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactNamingService.kt index 9c3be7736..783034181 100644 --- a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactNamingService.kt +++ b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactNamingService.kt @@ -21,7 +21,6 @@ import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.project.Project import com.intellij.psi.* import com.intellij.psi.util.ClassUtil -import org.jetbrains.uast.* import spp.jetbrains.marker.IArtifactNamingService import spp.jetbrains.marker.SourceMarker import spp.jetbrains.marker.jvm.service.utils.JVMMarkerUtils @@ -84,14 +83,7 @@ class JVMArtifactNamingService : IArtifactNamingService { } override fun getFullyQualifiedName(element: PsiElement): ArtifactQualifiedName { - return when (val uElement = element.toUElement()) { - is UClass -> JVMMarkerUtils.getFullyQualifiedName(uElement) - is UMethod -> JVMMarkerUtils.getFullyQualifiedName(uElement) - is UExpression -> JVMMarkerUtils.getFullyQualifiedName(element) - is UDeclaration -> JVMMarkerUtils.getFullyQualifiedName(element) - is UIdentifier -> JVMMarkerUtils.getFullyQualifiedName(element) - else -> TODO("Not yet implemented") - } + return JVMMarkerUtils.getFullyQualifiedName(element) } override fun getQualifiedClassNames(psiFile: PsiFile): List { diff --git a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactScopeService.kt b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactScopeService.kt index 647e6a508..2abb90e43 100644 --- a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactScopeService.kt +++ b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/JVMArtifactScopeService.kt @@ -22,6 +22,7 @@ import com.intellij.psi.scope.util.PsiScopesUtil import com.intellij.psi.util.parentOfTypes import com.siyeh.ig.psiutils.ControlFlowUtils import org.jetbrains.kotlin.psi.KtNamedFunction +import org.joor.Reflect import spp.jetbrains.marker.IArtifactScopeService import spp.jetbrains.marker.SourceMarkerUtils import spp.jetbrains.marker.source.SourceFileMarker @@ -34,14 +35,6 @@ import spp.jetbrains.marker.source.SourceFileMarker */ class JVMArtifactScopeService : IArtifactScopeService { - fun isMethodAtLine(psiFile: PsiFile, lineNumber: Int): Boolean { - var el = SourceMarkerUtils.getElementAtLine(psiFile, lineNumber) - while (el is PsiKeyword || el is PsiModifierList) { - el = el.parent - } - return el is PsiMethod - } - override fun getScopeVariables(fileMarker: SourceFileMarker, lineNumber: Int): List { //determine available vars var checkLine = lineNumber @@ -73,4 +66,15 @@ class JVMArtifactScopeService : IArtifactScopeService { } override fun isJVM(element: PsiElement): Boolean = true + + override fun canShowControlBar(psiElement: PsiElement): Boolean { + return when (psiElement::class.java.name) { + "org.jetbrains.kotlin.psi.KtObjectDeclaration" -> false + "org.jetbrains.kotlin.psi.KtProperty" -> { + Reflect.on(psiElement).call("isLocal").get() == true + } + + else -> super.canShowControlBar(psiElement) + } + } } diff --git a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/utils/JVMMarkerUtils.kt b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/utils/JVMMarkerUtils.kt index 45210267f..da6e66e88 100755 --- a/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/utils/JVMMarkerUtils.kt +++ b/marker/jvm-marker/src/main/kotlin/spp/jetbrains/marker/jvm/service/utils/JVMMarkerUtils.kt @@ -20,6 +20,8 @@ import com.intellij.lang.jvm.util.JvmClassUtil import com.intellij.openapi.diagnostic.logger import com.intellij.psi.* import com.intellij.psi.util.PsiUtil +import org.jetbrains.kotlin.psi.KtClass +import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.uast.* import org.joor.Reflect import spp.jetbrains.marker.SourceMarkerUtils @@ -59,8 +61,7 @@ object JVMMarkerUtils { autoApply: Boolean = false ): ExpressionInlayMark? { log.trace("getOrCreateExpressionInlayMark: $element") - val statementExpression: PsiElement = getUniversalExpression(element) - var lookupExpression: PsiElement = statementExpression + var lookupExpression: PsiElement = element if (lookupExpression is PsiDeclarationStatement) { //todo: support for multi-declaration statements lookupExpression = lookupExpression.firstChild @@ -73,12 +74,8 @@ object JVMMarkerUtils { SourceMark.Type.INLAY ) as ExpressionInlayMark? if (inlayMark != null) { - if (inlayMark.updatePsiExpression( - statementExpression, - getFullyQualifiedName(statementExpression.toUElement() as UExpression) - ) - ) { - statementExpression.putUserData(SourceKey.InlayMark, inlayMark) + if (inlayMark.updatePsiExpression(lookupExpression, getFullyQualifiedName(lookupExpression))) { + lookupExpression.putUserData(SourceKey.InlayMark, inlayMark) } else { inlayMark = null } @@ -87,22 +84,18 @@ object JVMMarkerUtils { return if (inlayMark == null) { inlayMark = fileMarker.createExpressionSourceMark( - statementExpression, + lookupExpression, SourceMark.Type.INLAY ) as ExpressionInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - null - } + inlayMark.apply(true) + inlayMark } else { inlayMark } } else { if (fileMarker.removeIfInvalid(inlayMark)) { - statementExpression.putUserData(SourceKey.InlayMark, null) + lookupExpression.putUserData(SourceKey.InlayMark, null) null } else { inlayMark @@ -131,10 +124,7 @@ object JVMMarkerUtils { SourceMark.Type.INLAY ) as ExpressionInlayMark? if (inlayMark != null) { - if (inlayMark.updatePsiExpression( - element, getFullyQualifiedName(element.toUElement() as UExpression) - ) - ) { + if (inlayMark.updatePsiExpression(element, getFullyQualifiedName(element))) { element.putUserData(SourceKey.InlayMark, inlayMark) } else { inlayMark = null @@ -143,19 +133,17 @@ object JVMMarkerUtils { } return if (inlayMark == null) { - val uExpression = element.toUElement() - if (uExpression !is UExpression && uExpression !is UDeclaration) return null + if (element.text != "}") { + val uExpression = element.toUElement() + if (uExpression !is UExpression && uExpression !is UDeclaration) return null + } inlayMark = fileMarker.createExpressionSourceMark( element, SourceMark.Type.INLAY ) as ExpressionInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - null - } + inlayMark.apply(true) + inlayMark } else { inlayMark } @@ -183,18 +171,13 @@ object JVMMarkerUtils { autoApply: Boolean = false ): ExpressionInlayMark { log.trace("createExpressionInlayMark: $element") - val statementExpression: PsiElement = getUniversalExpression(element) val inlayMark = fileMarker.createExpressionSourceMark( - statementExpression, + element, SourceMark.Type.INLAY ) as ExpressionInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - error("Could not apply inlay mark: $inlayMark") - } + inlayMark.apply(true) + inlayMark } else { inlayMark } @@ -219,12 +202,8 @@ object JVMMarkerUtils { SourceMark.Type.INLAY ) as ExpressionInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - error("Could not apply inlay mark: $inlayMark") - } + inlayMark.apply(true) + inlayMark } else { inlayMark } @@ -244,8 +223,7 @@ object JVMMarkerUtils { autoApply: Boolean = false ): ExpressionGutterMark? { log.trace("getOrCreateExpressionGutterMark: $element") - val statementExpression: PsiElement = getUniversalExpression(element) - var lookupExpression: PsiElement = statementExpression + var lookupExpression: PsiElement = element if (lookupExpression is PsiDeclarationStatement) { //todo: support for multi-declaration statements lookupExpression = lookupExpression.firstChild @@ -258,11 +236,8 @@ object JVMMarkerUtils { SourceMark.Type.GUTTER ) as ExpressionGutterMark? if (gutterMark != null) { - if (gutterMark.updatePsiExpression( - statementExpression, getFullyQualifiedName(statementExpression.toUElement() as UExpression) - ) - ) { - statementExpression.putUserData(SourceKey.GutterMark, gutterMark) + if (gutterMark.updatePsiExpression(lookupExpression, getFullyQualifiedName(lookupExpression))) { + lookupExpression.putUserData(SourceKey.GutterMark, gutterMark) } else { gutterMark = null } @@ -271,22 +246,18 @@ object JVMMarkerUtils { return if (gutterMark == null) { gutterMark = fileMarker.createExpressionSourceMark( - statementExpression, + lookupExpression, SourceMark.Type.GUTTER ) as ExpressionGutterMark return if (autoApply) { - if (gutterMark.canApply()) { - gutterMark.apply(true) - gutterMark - } else { - null - } + gutterMark.apply(true) + gutterMark } else { gutterMark } } else { if (fileMarker.removeIfInvalid(gutterMark)) { - statementExpression.putUserData(SourceKey.InlayMark, null) + lookupExpression.putUserData(SourceKey.InlayMark, null) null } else { gutterMark @@ -294,20 +265,6 @@ object JVMMarkerUtils { } } - /** - * todo: description. - * - * @since 0.1.0 - */ - @JvmStatic - fun getUniversalExpression(element: PsiStatement): PsiElement { - var statementExpression: PsiElement = element - if (statementExpression is PsiExpressionStatement) { - statementExpression = statementExpression.firstChild - } - return statementExpression - } - /** * todo: description. * @@ -339,12 +296,8 @@ object JVMMarkerUtils { SourceMark.Type.INLAY ) as MethodInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - null - } + inlayMark.apply(true) + inlayMark } else { inlayMark } @@ -394,12 +347,8 @@ object JVMMarkerUtils { SourceMark.Type.GUTTER ) as ClassGutterMark return if (autoApply) { - if (gutterMark.canApply()) { - gutterMark.apply(true) - gutterMark - } else { - null - } + gutterMark.apply(true) + gutterMark } else { gutterMark } @@ -433,63 +382,32 @@ object JVMMarkerUtils { return null } - /** - * todo: description. - * - * @since 0.1.0 - */ - @JvmStatic - fun getQualifiedClassName(qualifiedName: ArtifactQualifiedName): ArtifactQualifiedName { - var withoutArgs = qualifiedName.identifier.substring(0, qualifiedName.identifier.indexOf("(")) - val classQualifiedName = if (withoutArgs.contains("<")) { - withoutArgs = withoutArgs.substring(0, withoutArgs.indexOf("<")) - withoutArgs.substring(withoutArgs.lastIndexOf("?") + 1, withoutArgs.lastIndexOf(".")) - } else { - withoutArgs.substring(withoutArgs.lastIndexOf("?") + 1, withoutArgs.lastIndexOf(".")) - } - return ArtifactQualifiedName(classQualifiedName, type = ArtifactType.CLASS) - } - - /** - * todo: description. - * - * @since 0.1.0 - */ - @JvmStatic - fun getFullyQualifiedName(expression: UExpression): ArtifactQualifiedName { - val qualifiedMethodName = expression.getContainingUMethod()?.let { getFullyQualifiedName(it) } - return ArtifactQualifiedName( - """${qualifiedMethodName!!.identifier}#${ - Base64.getEncoder().encodeToString(expression.toString().toByteArray()) - }""", - type = ArtifactType.EXPRESSION, - lineNumber = expression.sourcePsi?.let { SourceMarkerUtils.getLineNumber(it) } - ) - } - @JvmStatic fun getFullyQualifiedName(element: PsiElement): ArtifactQualifiedName { - val expression = element.toUElement()!! - var expressionString = expression.sourcePsi?.text ?: expression.toString() - var parentIdentifier = expression.getContainingUMethod()?.let { getFullyQualifiedName(it) } - if (parentIdentifier == null) { - parentIdentifier = expression.sourcePsi?.findAnyContainingStrict(UMethod::class.java)?.let { - getFullyQualifiedName(it) - } + if (element is KtClass) { + return getFullyQualifiedName(element) + } else if (element is KtFunction) { + return getFullyQualifiedName(element) + } else if (element is PsiClass) { + return getFullyQualifiedName(element) + } else if (element is PsiMethod) { + return getFullyQualifiedName(element) } - if (parentIdentifier == null) { - parentIdentifier = expression.getContainingUClass()?.let { getFullyQualifiedName(it) } + + var expressionString = element.text + var parentIdentifier = element.findAnyContainingStrict(PsiMethod::class.java, KtFunction::class.java)?.let { + getFullyQualifiedName(it) } if (parentIdentifier == null) { - parentIdentifier = expression.sourcePsi?.findAnyContainingStrict(UClass::class.java)?.let { + parentIdentifier = element.findAnyContainingStrict(PsiClass::class.java, KtClass::class.java)?.let { getFullyQualifiedName(it) } } if (parentIdentifier == null) { - error("Could not determine parent of element: $element") + error("Could not determine parent of element: $element") //todo: extension function, see SourceMarkerConfig, make test } - expression.sourcePsi?.textRange?.startOffset?.let { + element.textRange.startOffset.let { expressionString = "$expressionString:$it" } return ArtifactQualifiedName( @@ -525,16 +443,42 @@ object JVMMarkerUtils { */ @JvmStatic fun getFullyQualifiedName(theClass: UClass): ArtifactQualifiedName { - return ArtifactQualifiedName("${JvmClassUtil.getJvmClassName(theClass)}", type = ArtifactType.CLASS) + return getFullyQualifiedName(theClass as PsiClass) + } + + @JvmStatic + fun getFullyQualifiedName(clazz: PsiClass): ArtifactQualifiedName { + return ArtifactQualifiedName( + "${JvmClassUtil.getJvmClassName(clazz)}", + type = ArtifactType.CLASS, + lineNumber = clazz.nameIdentifier?.let { SourceMarkerUtils.getLineNumber(it) } + ) + } + + @JvmStatic + private fun getFullyQualifiedName(theClass: KtClass): ArtifactQualifiedName { + return getFullyQualifiedName(theClass.toUElementOfType()!!) + } + + @JvmStatic + private fun getFullyQualifiedName(method: KtFunction): ArtifactQualifiedName { + return getFullyQualifiedName(method.toUElementOfType()!!) + } + + @JvmStatic + fun getFullyQualifiedName(method: PsiMethod): ArtifactQualifiedName { + val classQualifiedName = method.findAnyContainingStrict(PsiClass::class.java)?.let { + getFullyQualifiedName(it).identifier + } + return ArtifactQualifiedName( + "$classQualifiedName.${getQualifiedName(method)}", + type = ArtifactType.METHOD, + lineNumber = method.nameIdentifier?.let { SourceMarkerUtils.getLineNumber(it) } + ) } - /** - * todo: description. - * - * @since 0.1.0 - */ @JvmStatic - fun getQualifiedName(method: UMethod): String { + private fun getQualifiedName(method: PsiMethod): String { val methodName = method.nameIdentifier!!.text var methodParams = "" method.parameterList.parameters.forEach { @@ -577,14 +521,14 @@ object JVMMarkerUtils { return arrayDimensions } - private fun PsiElement?.findAnyContainingStrict( + private fun PsiElement?.findAnyContainingStrict( vararg types: Class ): T? { val depthLimit: Int = Integer.MAX_VALUE - var element = this + var element = this?.parent var i = 0 while (i < depthLimit && element != null && element !is PsiFileSystemItem) { - element.toUElement()?.let { + element.let { for (type in types) { if (type.isInstance(it)) { return it as T diff --git a/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/JVMArtifactNamingServiceTest.kt b/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/JVMArtifactNamingServiceTest.kt index e68469df3..761fc5d66 100644 --- a/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/JVMArtifactNamingServiceTest.kt +++ b/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/JVMArtifactNamingServiceTest.kt @@ -73,6 +73,7 @@ class JVMArtifactNamingServiceTest : BasePlatformTestCase() { val name = JVMArtifactNamingService().getFullyQualifiedName(clazz!!) assertEquals(getTestName(false) + "", name.identifier) assertEquals(ArtifactType.CLASS, name.type) + assertNotNull(name.lineNumber) } fun testJavaInnerClassName() { @@ -95,6 +96,7 @@ class JVMArtifactNamingServiceTest : BasePlatformTestCase() { val parentName = JVMArtifactNamingService().getFullyQualifiedName(clazz!!) assertEquals(getTestName(false) + "", parentName.identifier) assertEquals(ArtifactType.CLASS, parentName.type) + assertNotNull(parentName.lineNumber) val innerClazz = clazz.findDescendantOfType { it !== clazz } assertNotNull(innerClazz) @@ -102,6 +104,7 @@ class JVMArtifactNamingServiceTest : BasePlatformTestCase() { val innerName = JVMArtifactNamingService().getFullyQualifiedName(innerClazz!!) assertEquals(getTestName(false) + "\$InnerClassName", innerName.identifier) assertEquals(ArtifactType.CLASS, innerName.type) + assertNotNull(innerName.lineNumber) } fun testJavaMethodName() { @@ -124,6 +127,7 @@ class JVMArtifactNamingServiceTest : BasePlatformTestCase() { val name = JVMArtifactNamingService().getFullyQualifiedName(method!!) assertEquals(getTestName(false) + ".foo()", name.identifier) assertEquals(ArtifactType.METHOD, name.type) + assertNotNull(name.lineNumber) } fun testJavaInnerClassMethodName() { @@ -146,6 +150,7 @@ class JVMArtifactNamingServiceTest : BasePlatformTestCase() { val name = JVMArtifactNamingService().getFullyQualifiedName(method!!) assertEquals(getTestName(false) + "\$InnerClassName.foo()", name.identifier) assertEquals(ArtifactType.METHOD, name.type) + assertNotNull(name.lineNumber) } fun testJavaMethodVariable() { diff --git a/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/JVMGuideProviderTest.kt b/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/JVMGuideProviderTest.kt index 226035614..924e686f0 100644 --- a/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/JVMGuideProviderTest.kt +++ b/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/JVMGuideProviderTest.kt @@ -65,7 +65,7 @@ class JVMGuideProviderTest : BasePlatformTestCase() { private fun doTest(extension: String) { val psiFile = myFixture.configureByFile(getTestName(false) + ".$extension") - val fileMarker = SourceMarker.getInstance(myFixture.project).getSourceFileMarker(psiFile) + val fileMarker = SourceMarker.getSourceFileMarker(psiFile) assertNotNull(fileMarker) runBlocking { diff --git a/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/detect/JVMLoggerDetectorTest.kt b/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/detect/JVMLoggerDetectorTest.kt index a1a2a17e8..7e97ed631 100644 --- a/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/detect/JVMLoggerDetectorTest.kt +++ b/marker/jvm-marker/src/test/kotlin/spp/jetbrains/marker/jvm/detect/JVMLoggerDetectorTest.kt @@ -146,7 +146,7 @@ class JVMLoggerDetectorTest : LightJavaCodeInsightFixtureTestCase() { JVMMarker.setup() SourceFileMarker.SUPPORTED_FILE_TYPES.add(PsiJavaFile::class.java) - val fileMarker = SourceMarker.getInstance(project).getSourceFileMarker(sourceFile!!) + val fileMarker = SourceMarker.getSourceFileMarker(sourceFile!!) assertNotNull(fileMarker) val result = JVMLoggerDetector(project.apply { UserData.vertx(this, Vertx.vertx()) }) @@ -182,7 +182,7 @@ class JVMLoggerDetectorTest : LightJavaCodeInsightFixtureTestCase() { JVMMarker.setup() SourceFileMarker.SUPPORTED_FILE_TYPES.add(KtFile::class.java) - val fileMarker = SourceMarker.getInstance(project).getSourceFileMarker(sourceFile!!) + val fileMarker = SourceMarker.getSourceFileMarker(sourceFile!!) assertNotNull(fileMarker) val result = JVMLoggerDetector(project.apply { UserData.vertx(this, Vertx.vertx()) }) diff --git a/marker/py-marker/src/main/kotlin/spp/jetbrains/marker/py/PythonLineMarkerProvider.kt b/marker/py-marker/src/main/kotlin/spp/jetbrains/marker/py/PythonLineMarkerProvider.kt index 203571ed3..04aae1a81 100644 --- a/marker/py-marker/src/main/kotlin/spp/jetbrains/marker/py/PythonLineMarkerProvider.kt +++ b/marker/py-marker/src/main/kotlin/spp/jetbrains/marker/py/PythonLineMarkerProvider.kt @@ -19,7 +19,6 @@ package spp.jetbrains.marker.py import com.intellij.codeInsight.daemon.LineMarkerInfo import com.intellij.psi.PsiElement import com.jetbrains.python.psi.PyFile -import spp.jetbrains.marker.SourceMarker import spp.jetbrains.marker.plugin.SourceLineMarkerProvider import spp.jetbrains.marker.source.SourceFileMarker import spp.jetbrains.marker.source.mark.gutter.GutterMark @@ -39,7 +38,6 @@ class PythonLineMarkerProvider : SourceLineMarkerProvider() { } override fun getLineMarkerInfo(parent: PsiElement?, element: PsiElement): LineMarkerInfo? { - val fileMarker = SourceMarker.getInstance(element.project).getSourceFileMarker(element.containingFile) return null //todo: this } diff --git a/marker/py-marker/src/main/kotlin/spp/jetbrains/marker/py/service/PythonArtifactCreationService.kt b/marker/py-marker/src/main/kotlin/spp/jetbrains/marker/py/service/PythonArtifactCreationService.kt index 1f1a09ad2..8f1696dbe 100644 --- a/marker/py-marker/src/main/kotlin/spp/jetbrains/marker/py/service/PythonArtifactCreationService.kt +++ b/marker/py-marker/src/main/kotlin/spp/jetbrains/marker/py/service/PythonArtifactCreationService.kt @@ -84,12 +84,8 @@ class PythonArtifactCreationService : IArtifactCreationService { SourceMark.Type.GUTTER ) as ExpressionGutterMark return if (autoApply) { - if (gutterMark.canApply()) { - gutterMark.apply(true) - gutterMark - } else { - null - } + gutterMark.apply(true) + gutterMark } else { gutterMark } @@ -151,12 +147,8 @@ class PythonArtifactCreationService : IArtifactCreationService { SourceMark.Type.INLAY ) as ExpressionInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - error("Could not apply inlay mark: $inlayMark") - } + inlayMark.apply(true) + inlayMark } else { inlayMark } @@ -188,12 +180,8 @@ class PythonArtifactCreationService : IArtifactCreationService { SourceMark.Type.INLAY ) as ExpressionInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - null - } + inlayMark.apply(true) + inlayMark } else { inlayMark } diff --git a/marker/py-marker/src/test/kotlin/spp/jetbrains/marker/py/PythonGuideProviderTest.kt b/marker/py-marker/src/test/kotlin/spp/jetbrains/marker/py/PythonGuideProviderTest.kt index 190f9c375..6c1e01619 100644 --- a/marker/py-marker/src/test/kotlin/spp/jetbrains/marker/py/PythonGuideProviderTest.kt +++ b/marker/py-marker/src/test/kotlin/spp/jetbrains/marker/py/PythonGuideProviderTest.kt @@ -48,7 +48,7 @@ class PythonGuideProviderTest : BasePlatformTestCase() { fun testPythonMethod() { val psiFile = myFixture.configureByFile(getTestName(false) + ".py") - val fileMarker = SourceMarker.getInstance(myFixture.project).getSourceFileMarker(psiFile) + val fileMarker = SourceMarker.getSourceFileMarker(psiFile) assertNotNull(fileMarker) runBlocking { diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/IArtifactScopeService.kt b/marker/src/main/kotlin/spp/jetbrains/marker/IArtifactScopeService.kt index 78b7bba39..8bf04c9e9 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/IArtifactScopeService.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/IArtifactScopeService.kt @@ -31,4 +31,5 @@ interface IArtifactScopeService : ISourceMarkerService { fun isInsideFunction(element: PsiElement): Boolean fun isInsideEndlessLoop(element: PsiElement): Boolean = false fun isJVM(element: PsiElement): Boolean = false + fun canShowControlBar(psiElement: PsiElement): Boolean = true } diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarker.kt b/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarker.kt index 1f3a5bc12..76bcde3d1 100755 --- a/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarker.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarker.kt @@ -60,6 +60,10 @@ class SourceMarker { } return project.getUserData(KEY)!! } + + fun getSourceFileMarker(psiFile: PsiFile): SourceFileMarker? { + return getInstance(psiFile.project).getSourceFileMarker(psiFile) + } } @Volatile diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarkerConfiguration.kt b/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarkerConfiguration.kt index f0f266a67..2b64f97e9 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarkerConfiguration.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarkerConfiguration.kt @@ -18,7 +18,6 @@ package spp.jetbrains.marker import spp.jetbrains.marker.source.SourceFileMarker import spp.jetbrains.marker.source.SourceFileMarkerProvider -import spp.jetbrains.marker.source.mark.api.filter.CreateSourceMarkFilter import spp.jetbrains.marker.source.mark.guide.config.GuideMarkConfiguration import spp.jetbrains.marker.source.mark.gutter.config.GutterMarkConfiguration import spp.jetbrains.marker.source.mark.inlay.config.InlayMarkConfiguration @@ -30,7 +29,6 @@ import spp.jetbrains.marker.source.mark.inlay.config.InlayMarkConfiguration * @author [Brandon Fergerson](mailto:bfergerson@apache.org) */ class SourceMarkerConfiguration { - var createSourceMarkFilter: CreateSourceMarkFilter = CreateSourceMarkFilter.ALL var sourceFileMarkerProvider: SourceFileMarkerProvider = object : SourceFileMarkerProvider {} var gutterMarkConfiguration: GutterMarkConfiguration = GutterMarkConfiguration() var inlayMarkConfiguration: InlayMarkConfiguration = InlayMarkConfiguration() diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarkerUtils.kt b/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarkerUtils.kt index 30cb120d3..2429d80a0 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarkerUtils.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/SourceMarkerUtils.kt @@ -17,9 +17,8 @@ package spp.jetbrains.marker import com.intellij.openapi.editor.Document -import com.intellij.psi.PsiDocumentManager -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiFile +import com.intellij.psi.* +import com.intellij.psi.util.parentOfType import spp.jetbrains.marker.source.mark.api.SourceMark /** @@ -30,20 +29,6 @@ import spp.jetbrains.marker.source.mark.api.SourceMark */ object SourceMarkerUtils { - /** - * todo: description. - * - * @since 0.3.0 - */ - @JvmStatic - fun isBlankLine(psiFile: PsiFile, lineNumber: Int): Boolean { - val element = getElementAtLine(psiFile, lineNumber) - if (element != null) { - return getLineNumber(element) != lineNumber - } - return true - } - /** * todo: description. * @@ -61,6 +46,20 @@ object SourceMarkerUtils { val offset = document.getLineStartOffset(line - 1) var element = file.viewProvider.findElementAt(offset) if (element != null) { + //check for name identifier on same line (e.g. class/method name) + val nameIdentifierOwner = element.parentOfType() + if (nameIdentifierOwner != null && nameIdentifierOwner.nameIdentifier?.let { getLineNumber(it) } == line) { + return nameIdentifierOwner + } + + //check for annotation on same line + val annotation = element.parentOfType() + if (annotation != null && getLineNumber(annotation) == line) { + if (annotation.owner is PsiModifierList) { + return (annotation.owner as PsiModifierList).parent + } + } + if (document.getLineNumber(element.textOffset) != line - 1) { element = element.nextSibling } diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/impl/ArtifactScopeService.kt b/marker/src/main/kotlin/spp/jetbrains/marker/impl/ArtifactScopeService.kt index e94da413a..dd8ad3ad1 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/impl/ArtifactScopeService.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/impl/ArtifactScopeService.kt @@ -20,6 +20,8 @@ import com.intellij.psi.PsiElement import spp.jetbrains.marker.AbstractSourceMarkerService import spp.jetbrains.marker.IArtifactScopeService import spp.jetbrains.marker.source.SourceFileMarker +import spp.protocol.artifact.ArtifactQualifiedName +import spp.protocol.artifact.ArtifactType /** * todo: description. @@ -33,10 +35,18 @@ object ArtifactScopeService : AbstractSourceMarkerService return getService(fileMarker.psiFile.language).getScopeVariables(fileMarker, lineNumber) } + fun isOnFunction(qualifiedName: ArtifactQualifiedName): Boolean { + return qualifiedName.type == ArtifactType.METHOD + } + override fun isInsideFunction(element: PsiElement): Boolean { return getService(element.language).isInsideFunction(element) } + fun isOnOrInsideFunction(qualifiedName: ArtifactQualifiedName, element: PsiElement): Boolean { + return isOnFunction(qualifiedName) || isInsideFunction(element) + } + override fun isInsideEndlessLoop(element: PsiElement): Boolean { return getService(element.language).isInsideEndlessLoop(element) } diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/plugin/SourceInlayHintProvider.kt b/marker/src/main/kotlin/spp/jetbrains/marker/plugin/SourceInlayHintProvider.kt index 3a124df9b..aa881ce4a 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/plugin/SourceInlayHintProvider.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/plugin/SourceInlayHintProvider.kt @@ -146,14 +146,13 @@ abstract class SourceInlayHintProvider : InlayHintsProvider { return object : FactoryInlayHintsCollector(editor) { override fun collect(element: PsiElement, editor: Editor, sink: InlayHintsSink): Boolean { - val fileMarker = SourceMarker.getInstance(editor.project!!).getSourceFileMarker(element.containingFile) ?: return true + val fileMarker = SourceMarker.getSourceFileMarker(element.containingFile) ?: return true var inlayMark = element.getUserData(SourceKey.InlayMark) if (inlayMark == null) { if (SourceMarker.getInstance(editor.project!!).configuration.inlayMarkConfiguration.strictlyManualCreation) return true else { inlayMark = createInlayMarkIfNecessary(element) ?: return true } } - if (!fileMarker.containsSourceMark(inlayMark) && !inlayMark.canApply()) return true if (!fileMarker.containsSourceMark(inlayMark)) inlayMark.apply() if (!inlayMark.isVisible()) { return true diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/plugin/SourceLineMarkerProvider.kt b/marker/src/main/kotlin/spp/jetbrains/marker/plugin/SourceLineMarkerProvider.kt index b136a5c68..091193788 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/plugin/SourceLineMarkerProvider.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/plugin/SourceLineMarkerProvider.kt @@ -87,7 +87,7 @@ abstract class SourceLineMarkerProvider : LineMarkerProviderDescriptor() { } elements.stream().map { it.containingFile }.distinct().forEach { - SourceMarker.getInstance(it.project).getSourceFileMarker(it)?.removeInvalidSourceMarks() + SourceMarker.getSourceFileMarker(it)?.removeInvalidSourceMarks() } } diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/SourceFileMarker.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/SourceFileMarker.kt index 0fe6560fb..559280e18 100755 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/SourceFileMarker.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/source/SourceFileMarker.kt @@ -150,28 +150,25 @@ open class SourceFileMarker(val psiFile: PsiFile) : SourceMarkProvider { @JvmOverloads open fun applySourceMark( sourceMark: SourceMark, - autoRefresh: Boolean = false, - overrideFilter: Boolean = false + autoRefresh: Boolean = false ): Boolean { - if (overrideFilter || sourceMark.canApply()) { - log.trace("Applying source mark for artifact: $sourceMark") - sourceMark.triggerEvent(SourceMarkEvent(sourceMark, SourceMarkEventCode.MARK_BEFORE_ADDED)) - if (sourceMarks.add(sourceMark)) { - when (sourceMark) { - is ClassGutterMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.GutterMark, sourceMark) - is ClassGuideMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.GuideMark, sourceMark) - is MethodGutterMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.GutterMark, sourceMark) - is MethodInlayMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.InlayMark, sourceMark) - is MethodGuideMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.GuideMark, sourceMark) - is ExpressionGutterMark -> sourceMark.getPsiElement().putUserData(SourceKey.GutterMark, sourceMark) - is ExpressionInlayMark -> sourceMark.getPsiElement().putUserData(SourceKey.InlayMark, sourceMark) - is ExpressionGuideMark -> sourceMark.getPsiElement().putUserData(SourceKey.GuideMark, sourceMark) - } - - if (autoRefresh) refresh() - log.trace("Applied source mark for artifact: $sourceMark") - return true + log.trace("Applying source mark for artifact: $sourceMark") + sourceMark.triggerEvent(SourceMarkEvent(sourceMark, SourceMarkEventCode.MARK_BEFORE_ADDED)) + if (sourceMarks.add(sourceMark)) { + when (sourceMark) { + is ClassGutterMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.GutterMark, sourceMark) + is ClassGuideMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.GuideMark, sourceMark) + is MethodGutterMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.GutterMark, sourceMark) + is MethodInlayMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.InlayMark, sourceMark) + is MethodGuideMark -> sourceMark.getNameIdentifier().putUserData(SourceKey.GuideMark, sourceMark) + is ExpressionGutterMark -> sourceMark.getPsiElement().putUserData(SourceKey.GutterMark, sourceMark) + is ExpressionInlayMark -> sourceMark.getPsiElement().putUserData(SourceKey.InlayMark, sourceMark) + is ExpressionGuideMark -> sourceMark.getPsiElement().putUserData(SourceKey.GuideMark, sourceMark) } + + if (autoRefresh) refresh() + log.trace("Applied source mark for artifact: $sourceMark") + return true } return false } @@ -255,12 +252,8 @@ open class SourceFileMarker(val psiFile: PsiFile) : SourceMarkProvider { SourceMark.Type.GUTTER ) as MethodGutterMark return if (autoApply) { - if (gutterMark.canApply()) { - gutterMark.apply(true) - gutterMark - } else { - error("Could not apply gutter mark: $gutterMark") - } + gutterMark.apply(true) + gutterMark } else { gutterMark } @@ -276,12 +269,8 @@ open class SourceFileMarker(val psiFile: PsiFile) : SourceMarkProvider { SourceMark.Type.INLAY ) as MethodInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - error("Could not apply inlay mark: $inlayMark") - } + inlayMark.apply(true) + inlayMark } else { inlayMark } @@ -297,12 +286,8 @@ open class SourceFileMarker(val psiFile: PsiFile) : SourceMarkProvider { SourceMark.Type.GUTTER ) as ExpressionGutterMark return if (autoApply) { - if (gutterMark.canApply()) { - gutterMark.apply(true) - gutterMark - } else { - error("Could not apply gutter mark: $gutterMark") - } + gutterMark.apply(true) + gutterMark } else { gutterMark } @@ -318,12 +303,8 @@ open class SourceFileMarker(val psiFile: PsiFile) : SourceMarkProvider { SourceMark.Type.INLAY ) as ExpressionInlayMark return if (autoApply) { - if (inlayMark.canApply()) { - inlayMark.apply(true) - inlayMark - } else { - error("Could not apply inlay mark: $inlayMark") - } + inlayMark.apply(true) + inlayMark } else { inlayMark } diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/SourceMark.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/SourceMark.kt index 32d612c2d..dfff51bd2 100755 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/SourceMark.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/SourceMark.kt @@ -137,8 +137,6 @@ interface SourceMark : JBPopupListener, MouseMotionListener, VisibleAreaListener fun isVisible(): Boolean fun setVisible(visible: Boolean) - fun canApply(): Boolean = configuration.applySourceMarkFilter.test(this) - fun applyIfMissing() { if (!sourceFileMarker.containsSourceMark(this)) { apply(true) @@ -149,7 +147,7 @@ interface SourceMark : JBPopupListener, MouseMotionListener, VisibleAreaListener fun apply(addToMarker: Boolean = true, editor: Editor? = null) { SourceMarker.getInstance(project).getGlobalSourceMarkEventListeners().forEach(::addEventListener) - if (addToMarker && sourceFileMarker.applySourceMark(this, autoRefresh = true, overrideFilter = true)) { + if (addToMarker && sourceFileMarker.applySourceMark(this, autoRefresh = true)) { triggerEvent(SourceMarkEvent(this, SourceMarkEventCode.MARK_ADDED)) if (this is GutterMark) { @@ -168,60 +166,56 @@ interface SourceMark : JBPopupListener, MouseMotionListener, VisibleAreaListener } } else if (this is InlayMark) { if (configuration.showComponentInlay) { - val selectedEditor = editor ?: FileEditorManager.getInstance(project).selectedTextEditor - if (selectedEditor == null) { - TODO() - } else { - val provider = SourceInlayComponentProvider.from(selectedEditor) - val viewport = (selectedEditor as? EditorImpl)?.scrollPane?.viewport!! - var displayLineIndex = lineNumber - 1 - if (this is ExpressionInlayMark) { - if (showAboveExpression) { - displayLineIndex-- - } + val selectedEditor = editor ?: FileEditorManager.getInstance(project).selectedTextEditor!! + val provider = SourceInlayComponentProvider.from(selectedEditor) + val viewport = (selectedEditor as? EditorImpl)?.scrollPane?.viewport!! + var displayLineIndex = artifactQualifiedName.lineNumber!! - 1 + if (this is ExpressionInlayMark) { + if (showAboveExpression) { + displayLineIndex-- } + } - if (isVisible()) { - val inlay = provider.insertAfter( - displayLineIndex, - configuration.componentProvider.getComponent(this).getComponent() - ) - configuration.inlayRef = Ref.create() - configuration.inlayRef!!.set(inlay) - viewport.dispatchEvent(ComponentEvent(viewport, ComponentEvent.COMPONENT_RESIZED)) - - //initial mark visible event - triggerEvent(SourceMarkEvent(this, INLAY_MARK_VISIBLE)) - } else { - setVisible(false) - } + if (isVisible()) { + val inlay = provider.insertAfter( + displayLineIndex, + configuration.componentProvider.getComponent(this).getComponent() + ) + configuration.inlayRef = Ref.create() + configuration.inlayRef!!.set(inlay) + viewport.dispatchEvent(ComponentEvent(viewport, ComponentEvent.COMPONENT_RESIZED)) - addEventListener(SynchronousSourceMarkEventListener { - when (it.eventCode) { - INLAY_MARK_VISIBLE -> { - ApplicationManager.getApplication().invokeLater { - configuration.inlayRef = Ref.create() - configuration.inlayRef!!.set( - provider.insertAfter( - displayLineIndex, - configuration.componentProvider.getComponent(this).getComponent() - ) - ) - viewport.dispatchEvent( - ComponentEvent(viewport, ComponentEvent.COMPONENT_RESIZED) + //initial mark visible event + triggerEvent(SourceMarkEvent(this, INLAY_MARK_VISIBLE)) + } else { + setVisible(false) + } + + addEventListener(SynchronousSourceMarkEventListener { + when (it.eventCode) { + INLAY_MARK_VISIBLE -> { + ApplicationManager.getApplication().invokeLater { + configuration.inlayRef = Ref.create() + configuration.inlayRef!!.set( + provider.insertAfter( + displayLineIndex, + configuration.componentProvider.getComponent(this).getComponent() ) - } + ) + viewport.dispatchEvent( + ComponentEvent(viewport, ComponentEvent.COMPONENT_RESIZED) + ) } + } - INLAY_MARK_HIDDEN -> { - ApplicationManager.getApplication().invokeLater { - configuration.inlayRef?.get()?.dispose() - configuration.inlayRef = null - } + INLAY_MARK_HIDDEN -> { + ApplicationManager.getApplication().invokeLater { + configuration.inlayRef?.get()?.dispose() + configuration.inlayRef = null } } - }) - } + } + }) } else { ApplicationManager.getApplication().invokeLater { InlayHintsPassFactory.forceHintsUpdateOnNextPass() diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/component/tooltip/LiveTooltip.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/component/tooltip/LiveTooltip.kt index 6feabdd93..5793eccc8 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/component/tooltip/LiveTooltip.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/component/tooltip/LiveTooltip.kt @@ -136,7 +136,7 @@ open class LiveTooltip(val guideMark: GuideMark, var panel: JPanel? = null) { private fun getLiveDisplays(editor: Editor): List { val project = editor.project ?: return emptyList() val psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.document) ?: return emptyList() - return SourceMarker.getInstance(project).getSourceFileMarker(psiFile) + return SourceMarker.getSourceFileMarker(psiFile) ?.getSourceMarks()?.filterIsInstance()?.mapNotNull { it.configuration.liveTooltip } ?: emptyList() } diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/config/SourceMarkConfiguration.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/config/SourceMarkConfiguration.kt index c6af9990b..49755307c 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/config/SourceMarkConfiguration.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/config/SourceMarkConfiguration.kt @@ -18,7 +18,6 @@ package spp.jetbrains.marker.source.mark.api.config import spp.jetbrains.marker.source.mark.api.SourceMark import spp.jetbrains.marker.source.mark.api.component.api.SourceMarkComponentProvider -import spp.jetbrains.marker.source.mark.api.filter.ApplySourceMarkFilter /** * Used to configure [SourceMark]s. @@ -27,7 +26,6 @@ import spp.jetbrains.marker.source.mark.api.filter.ApplySourceMarkFilter * @author [Brandon Fergerson](mailto:bfergerson@apache.org) */ interface SourceMarkConfiguration { - var applySourceMarkFilter: ApplySourceMarkFilter var activateOnKeyboardShortcut: Boolean var componentProvider: SourceMarkComponentProvider } diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/filter/ApplySourceMarkFilter.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/filter/ApplySourceMarkFilter.kt deleted file mode 100644 index 20448346a..000000000 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/filter/ApplySourceMarkFilter.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Source++, the open-source live coding platform. - * Copyright (C) 2022 CodeBrig, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package spp.jetbrains.marker.source.mark.api.filter - -import spp.jetbrains.marker.source.mark.api.SourceMark -import java.util.function.Predicate - -/** - * Used to filter auto-applied [SourceMark]s. - * - * @since 0.1.0 - * @author [Brandon Fergerson](mailto:bfergerson@apache.org) - */ -fun interface ApplySourceMarkFilter : Predicate { - companion object { - @JvmStatic - val ALL: ApplySourceMarkFilter = ApplySourceMarkFilter { true } - - @JvmStatic - val NONE: ApplySourceMarkFilter = ApplySourceMarkFilter { false } - } -} diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/filter/CreateSourceMarkFilter.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/filter/CreateSourceMarkFilter.kt deleted file mode 100644 index b5ac6a894..000000000 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/api/filter/CreateSourceMarkFilter.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Source++, the open-source live coding platform. - * Copyright (C) 2022 CodeBrig, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package spp.jetbrains.marker.source.mark.api.filter - -import spp.jetbrains.marker.source.mark.api.SourceMark -import spp.protocol.artifact.ArtifactQualifiedName -import java.util.function.Predicate - -/** - * Used to filter auto-created [SourceMark]s. - * - * @since 0.1.0 - * @author [Brandon Fergerson](mailto:bfergerson@apache.org) - */ -fun interface CreateSourceMarkFilter : Predicate { - companion object { - @JvmStatic - val ALL: CreateSourceMarkFilter = CreateSourceMarkFilter { true } - - @JvmStatic - val NONE: CreateSourceMarkFilter = CreateSourceMarkFilter { false } - } -} diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/guide/config/GuideMarkConfiguration.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/guide/config/GuideMarkConfiguration.kt index b182a568d..edb6518af 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/guide/config/GuideMarkConfiguration.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/guide/config/GuideMarkConfiguration.kt @@ -20,7 +20,6 @@ import spp.jetbrains.marker.source.mark.api.component.api.SourceMarkComponentPro import spp.jetbrains.marker.source.mark.api.component.jcef.SourceMarkJcefComponentProvider import spp.jetbrains.marker.source.mark.api.component.tooltip.LiveTooltip import spp.jetbrains.marker.source.mark.api.config.SourceMarkConfiguration -import spp.jetbrains.marker.source.mark.api.filter.ApplySourceMarkFilter import spp.jetbrains.marker.source.mark.guide.GuideMark /** @@ -31,7 +30,6 @@ import spp.jetbrains.marker.source.mark.guide.GuideMark */ data class GuideMarkConfiguration( var liveTooltip: LiveTooltip? = null, - override var applySourceMarkFilter: ApplySourceMarkFilter = ApplySourceMarkFilter.ALL, override var activateOnKeyboardShortcut: Boolean = false, override var componentProvider: SourceMarkComponentProvider = SourceMarkJcefComponentProvider() ) : SourceMarkConfiguration diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/gutter/config/GutterMarkConfiguration.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/gutter/config/GutterMarkConfiguration.kt index 9eb9f5583..2892c9597 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/gutter/config/GutterMarkConfiguration.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/gutter/config/GutterMarkConfiguration.kt @@ -19,7 +19,6 @@ package spp.jetbrains.marker.source.mark.gutter.config import spp.jetbrains.marker.source.mark.api.component.api.SourceMarkComponentProvider import spp.jetbrains.marker.source.mark.api.component.jcef.SourceMarkJcefComponentProvider import spp.jetbrains.marker.source.mark.api.config.SourceMarkConfiguration -import spp.jetbrains.marker.source.mark.api.filter.ApplySourceMarkFilter import spp.jetbrains.marker.source.mark.gutter.GutterMark import javax.swing.Icon @@ -30,7 +29,6 @@ import javax.swing.Icon * @author [Brandon Fergerson](mailto:bfergerson@apache.org) */ data class GutterMarkConfiguration( - override var applySourceMarkFilter: ApplySourceMarkFilter = ApplySourceMarkFilter.ALL, var tooltipText: (() -> String)? = null, var icon: Icon? = null, var activateOnMouseHover: Boolean = true, diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/inlay/ExpressionInlayMark.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/inlay/ExpressionInlayMark.kt index cc87fe99b..fcc4298b8 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/inlay/ExpressionInlayMark.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/inlay/ExpressionInlayMark.kt @@ -21,6 +21,7 @@ import spp.jetbrains.marker.SourceMarker import spp.jetbrains.marker.plugin.action.SourceMarkerVisibilityAction import spp.jetbrains.marker.source.SourceFileMarker import spp.jetbrains.marker.source.mark.api.ExpressionSourceMark +import spp.protocol.artifact.ArtifactType import java.util.* import java.util.concurrent.atomic.AtomicBoolean @@ -39,4 +40,11 @@ class ExpressionInlayMark constructor( override val configuration = SourceMarker.getInstance(project).configuration.inlayMarkConfiguration.copy() override var visible = AtomicBoolean(SourceMarkerVisibilityAction.globalVisibility) var showAboveExpression = false + + init { + //show above element by default for method and class artifacts + if (artifactQualifiedName.type in listOf(ArtifactType.METHOD, ArtifactType.CLASS)) { + showAboveExpression = true + } + } } diff --git a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/inlay/config/InlayMarkConfiguration.kt b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/inlay/config/InlayMarkConfiguration.kt index 1b7d2b738..1fb3f6949 100644 --- a/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/inlay/config/InlayMarkConfiguration.kt +++ b/marker/src/main/kotlin/spp/jetbrains/marker/source/mark/inlay/config/InlayMarkConfiguration.kt @@ -21,7 +21,6 @@ import com.intellij.openapi.util.Ref import spp.jetbrains.marker.source.mark.api.component.api.SourceMarkComponentProvider import spp.jetbrains.marker.source.mark.api.component.jcef.SourceMarkJcefComponentProvider import spp.jetbrains.marker.source.mark.api.config.SourceMarkConfiguration -import spp.jetbrains.marker.source.mark.api.filter.ApplySourceMarkFilter import spp.jetbrains.marker.source.mark.inlay.InlayMark /** @@ -31,7 +30,6 @@ import spp.jetbrains.marker.source.mark.inlay.InlayMark * @author [Brandon Fergerson](mailto:bfergerson@apache.org) */ data class InlayMarkConfiguration( - override var applySourceMarkFilter: ApplySourceMarkFilter = ApplySourceMarkFilter.NONE, var strictlyManualCreation: Boolean = false, var virtualText: InlayMarkVirtualText? = null, var showComponentInlay: Boolean = false, diff --git a/plugin/src/main/java/spp/jetbrains/sourcemarker/ControlBar.java b/plugin/src/main/java/spp/jetbrains/sourcemarker/ControlBar.java index 7a0424036..f6135fc0a 100644 --- a/plugin/src/main/java/spp/jetbrains/sourcemarker/ControlBar.java +++ b/plugin/src/main/java/spp/jetbrains/sourcemarker/ControlBar.java @@ -60,7 +60,6 @@ public ControlBar(Editor editor, InlayMark inlayMark, List availabl this.inlayMark = inlayMark; LiveLocationContext context = new LiveLocationContext( - inlayMark.getLineNumber(), inlayMark.getArtifactQualifiedName(), inlayMark.getSourceFileMarker(), inlayMark.getPsiElement() @@ -94,9 +93,9 @@ public ControlBar(Editor editor, InlayMark inlayMark, List availabl textField1.addSaveListener(() -> { String autoCompleteText = textField1.getSelectedText(); if (autoCompleteText != null) { - ControlBarController.INSTANCE.handleCommandInput(autoCompleteText, editor); + ControlBarController.handleCommandInput(autoCompleteText, editor); } else { - ControlBarController.INSTANCE.handleCommandInput(textField1.getText(), editor); + ControlBarController.handleCommandInput(textField1.getText(), editor); } }); } @@ -119,22 +118,16 @@ public void keyPressed(KeyEvent e) { //ignore tab; handled by auto-complete e.consume(); } else if (e.getKeyCode() == KeyEvent.VK_UP && !textField1.isPopupVisible()) { - int lineNumber = inlayMark.getLineNumber(); - while (--lineNumber > 0) { - if (ControlBarController.INSTANCE.canShowControlBar(inlayMark.getSourceFileMarker(), lineNumber)) { - dispose(); - ControlBarController.INSTANCE.showControlBar(editor, lineNumber, true); - break; - } + Integer nextLine = ControlBarController.getNextAvailableControlBarLine(editor, inlayMark, true); + if (nextLine != null) { + dispose(); + ControlBarController.showControlBar(editor, nextLine); } } else if (e.getKeyCode() == KeyEvent.VK_DOWN && !textField1.isPopupVisible()) { - int lineNumber = inlayMark.getLineNumber(); - while (++lineNumber < editor.getDocument().getLineCount()) { - if (ControlBarController.INSTANCE.canShowControlBar(inlayMark.getSourceFileMarker(), lineNumber)) { - dispose(); - ControlBarController.INSTANCE.showControlBar(editor, lineNumber, true); - break; - } + Integer nextLine = ControlBarController.getNextAvailableControlBarLine(editor, inlayMark, false); + if (nextLine != null) { + dispose(); + ControlBarController.showControlBar(editor, nextLine); } } } @@ -147,13 +140,13 @@ public void keyTyped(KeyEvent e) { if (!textField1.getReady()) return; String autoCompleteText = textField1.getSelectedText(); if (autoCompleteText != null) { - ControlBarController.INSTANCE.handleCommandInput(autoCompleteText, textField1.getActualText(), editor); + ControlBarController.handleCommandInput(autoCompleteText, textField1.getActualText(), editor); } else if (!textField1.getText().isEmpty()) { List commands = lookup.apply(textField1.getText()); if (commands.isEmpty()) { - ControlBarController.INSTANCE.handleCommandInput(textField1.getText(), editor); + ControlBarController.handleCommandInput(textField1.getText(), editor); } else { - ControlBarController.INSTANCE.handleCommandInput(commands.get(0).getText(), editor); + ControlBarController.handleCommandInput(commands.get(0).getText(), editor); } } } @@ -222,9 +215,13 @@ private void initComponents() { inlayMark.getLanguage(), inlayMark.getArtifactQualifiedName() ); - textField1 = new AutocompleteField( + location = message("location") + ": " + location; + if (inlayMark.getArtifactQualifiedName().getType().showLineNumber()) { + location += "#" + inlayMark.getLineNumber(); + } + textField1 = new AutocompleteField<>( inlayMark.getProject(), - message("location") + ": " + location + "#" + inlayMark.getLineNumber(), + location, availableCommands, lookup, inlayMark.getArtifactQualifiedName(), true); textField1.setReplaceCommandOnTab(true); textField1.setAutocompleteAndFinishOnEnter(true); diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarAction.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarAction.kt index d9ac23d61..c0de35b43 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarAction.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarAction.kt @@ -20,10 +20,9 @@ import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent import com.intellij.openapi.actionSystem.PlatformDataKeys import com.intellij.openapi.project.Project -import com.intellij.openapi.util.TextRange /** - * todo: description. + * Shows the Live Command Palette on keyboard shortcut. * * @since 0.3.0 * @author [Brandon Fergerson](mailto:bfergerson@apache.org) @@ -38,15 +37,6 @@ class ControlBarAction : AnAction() { override fun actionPerformed(e: AnActionEvent) { val editor = e.getData(PlatformDataKeys.EDITOR) ?: return val lineNumber = editor.document.getLineNumber(editor.caretModel.offset) - val lineStart = editor.document.getLineStartOffset(lineNumber) - val lineEnd = editor.document.getLineEndOffset(lineNumber) - val text = editor.document.getText(TextRange(lineStart, lineEnd)) - val codeStartsAt = text.length - text.trimStart().length - if (editor.caretModel.offset <= lineStart + codeStartsAt) { - //caret is before the current line's code - ControlBarController.showControlBar(editor, lineNumber) - } else { - ControlBarController.showControlBar(editor, lineNumber + 1) - } + ControlBarController.showControlBar(editor, lineNumber + 1) } } diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarController.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarController.kt index 38fb1fe82..cea27cd0b 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarController.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/command/ControlBarController.kt @@ -19,15 +19,14 @@ package spp.jetbrains.sourcemarker.command import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.editor.Editor import com.intellij.psi.PsiDocumentManager -import com.intellij.psi.PsiElement import liveplugin.implementation.common.toFilePath -import org.joor.Reflect import spp.jetbrains.ScopeExtensions.safeRunBlocking import spp.jetbrains.command.LiveCommand import spp.jetbrains.command.LiveCommandContext import spp.jetbrains.command.LiveLocationContext import spp.jetbrains.marker.impl.ArtifactCreationService import spp.jetbrains.marker.impl.ArtifactNamingService +import spp.jetbrains.marker.impl.ArtifactScopeService import spp.jetbrains.marker.source.SourceFileMarker import spp.jetbrains.marker.source.mark.api.SourceMark import spp.jetbrains.marker.source.mark.api.component.swing.SwingSourceMarkComponentProvider @@ -56,7 +55,6 @@ object ControlBarController { availableCommandsAtLocation.addAll( LivePluginService.getInstance(inlayMark.project).getRegisteredLiveCommands( LiveLocationContext( - inlayMark.lineNumber, inlayMark.artifactQualifiedName, inlayMark.sourceFileMarker, inlayMark.getPsiElement() @@ -66,10 +64,12 @@ object ControlBarController { return availableCommandsAtLocation.toList() } + @JvmStatic fun handleCommandInput(input: String, editor: Editor) { handleCommandInput(input, input, editor) } + @JvmStatic fun handleCommandInput(input: String, fullText: String, editor: Editor) { log.info("Processing command input: $input") LivePluginService.getInstance(editor.project!!).getRegisteredLiveCommands() @@ -103,7 +103,8 @@ object ControlBarController { /** * Attempts to display live control bar below [lineNumber]. */ - fun showControlBar(editor: Editor, lineNumber: Int, tryingAboveLine: Boolean = false) { + @JvmStatic + fun showControlBar(editor: Editor, lineNumber: Int) { //close previous control bar (if open) previousControlBar?.dispose(true, false) previousControlBar = null @@ -117,14 +118,9 @@ object ControlBarController { } val findInlayMark = ArtifactCreationService.getOrCreateExpressionInlayMark(fileMarker, lineNumber) - if (findInlayMark.isPresent && canShowControlBar(findInlayMark.get().getPsiElement())) { + if (findInlayMark.isPresent && ArtifactScopeService.canShowControlBar(findInlayMark.get().getPsiElement())) { val inlayMark = findInlayMark.get() - if (fileMarker.containsSourceMark(inlayMark)) { - if (!tryingAboveLine) { - //already showing inlay here, try line above - showControlBar(editor, lineNumber - 1, true) - } - } else { + if (!fileMarker.containsSourceMark(inlayMark)) { //create and display control bar previousControlBar = inlayMark @@ -144,27 +140,35 @@ object ControlBarController { controlBar.focus() } - } else if (tryingAboveLine) { - log.warn("No detected expression at line $lineNumber. Inlay mark ignored") - } else { - showControlBar(editor, lineNumber - 1, true) } } - fun canShowControlBar(fileMarker: SourceFileMarker, lineNumber: Int): Boolean { - val expressionInlayMark = ArtifactCreationService.getOrCreateExpressionInlayMark(fileMarker, lineNumber) - return expressionInlayMark.isPresent && canShowControlBar(expressionInlayMark.get().getPsiElement()) + private fun canShowControlBar(fileMarker: SourceFileMarker, lineNumber: Int): InlayMark? { + val inlayMark = ArtifactCreationService.getOrCreateExpressionInlayMark(fileMarker, lineNumber) + return if (inlayMark.isPresent && ArtifactScopeService.canShowControlBar(inlayMark.get().getPsiElement())) { + inlayMark.get() + } else null } - private fun canShowControlBar(psiElement: PsiElement): Boolean { - return when (psiElement::class.java.name) { - "org.jetbrains.kotlin.psi.KtObjectDeclaration" -> false - "org.jetbrains.kotlin.psi.KtProperty" -> { - Reflect.on(psiElement).call("isLocal").get() == true + @JvmStatic + fun getNextAvailableControlBarLine(editor: Editor, inlayMark: InlayMark, moveUp: Boolean): Int? { + var lineNumber = inlayMark.artifactQualifiedName.lineNumber!! + if (moveUp) { + while (--lineNumber > 0) { + val nextMark = canShowControlBar(inlayMark.sourceFileMarker, lineNumber) + if (nextMark != null && nextMark.artifactQualifiedName != inlayMark.artifactQualifiedName) { + return lineNumber + } + } + } else { + while (++lineNumber < editor.document.lineCount) { + val nextMark = canShowControlBar(inlayMark.sourceFileMarker, lineNumber) + if (nextMark != null && nextMark.artifactQualifiedName != inlayMark.artifactQualifiedName) { + return lineNumber + } } - - else -> true } + return null } private fun substringAfterIgnoreCase(str: String, search: String): String { diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/mark/PluginSourceMarkEventListener.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/mark/PluginSourceMarkEventListener.kt index cbf5fda89..f5749bf87 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/mark/PluginSourceMarkEventListener.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/mark/PluginSourceMarkEventListener.kt @@ -87,7 +87,7 @@ class PluginSourceMarkEventListener(val project: Project, val vertx: Vertx) : Sy FileEditorManager.getInstance(project).allEditors.forEach { ApplicationManager.getApplication().runReadAction { PsiManager.getInstance(project).findFile(it.file)?.let { - SourceMarker.getInstance(project).getSourceFileMarker(it) + SourceMarker.getSourceFileMarker(it) DaemonCodeAnalyzer.getInstance(project).restart(it) } } diff --git a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/status/util/ControlBarCellRenderer.kt b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/status/util/ControlBarCellRenderer.kt index 52335d3cb..ae2694cfd 100644 --- a/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/status/util/ControlBarCellRenderer.kt +++ b/plugin/src/main/kotlin/spp/jetbrains/sourcemarker/status/util/ControlBarCellRenderer.kt @@ -55,7 +55,6 @@ class ControlBarCellRenderer( row.setCommandIcon(rowValue.getUnselectedIcon()) val context = LiveLocationContext( - autocompleteField.artifactQualifiedName.lineNumber!!, autocompleteField.artifactQualifiedName, inlayMark.sourceFileMarker, inlayMark.getPsiElement()