Initial implementation of method separators

#KT-13029 Fixed
This commit is contained in:
Dmitry Jemerov
2018-01-03 17:22:27 +01:00
parent fd01351740
commit 86c10b635a
5 changed files with 88 additions and 31 deletions
@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* 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.
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.test;
@@ -115,6 +104,9 @@ public final class InTextDirectivesUtils {
@NotNull
public static List<String> findLinesWithPrefixesRemoved(String fileText, boolean trim, String... prefixes) {
if (prefixes.length == 0) {
throw new IllegalArgumentException("Please specify the prefixes to check");
}
List<String> result = new ArrayList<>();
List<String> cleanedPrefixes = cleanDirectivesFromComments(Arrays.asList(prefixes));
@@ -6,24 +6,26 @@
package org.jetbrains.kotlin.idea.highlighter.markers
import com.intellij.codeHighlighting.Pass
import com.intellij.codeInsight.daemon.GutterIconNavigationHandler
import com.intellij.codeInsight.daemon.LineMarkerInfo
import com.intellij.codeInsight.daemon.LineMarkerProvider
import com.intellij.codeInsight.daemon.NavigateAction
import com.intellij.codeInsight.daemon.*
import com.intellij.codeInsight.daemon.impl.LineMarkerNavigator
import com.intellij.codeInsight.daemon.impl.MarkerType
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator
import com.intellij.codeInsight.navigation.ListBackgroundUpdaterTask
import com.intellij.icons.AllIcons
import com.intellij.openapi.actionSystem.IdeActions
import com.intellij.openapi.editor.colors.CodeInsightColors
import com.intellij.openapi.editor.colors.EditorColorsManager
import com.intellij.openapi.editor.markup.GutterIconRenderer
import com.intellij.openapi.editor.markup.SeparatorPlacement
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.DumbService
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.NavigatablePsiElement
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiNameIdentifierOwner
import com.intellij.psi.search.searches.ClassInheritorsSearch
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
@@ -42,6 +44,7 @@ import org.jetbrains.kotlin.idea.search.declarationsSearch.toPossiblyFakeLightMe
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments
import java.awt.event.MouseEvent
import java.util.*
import javax.swing.Icon
@@ -49,10 +52,33 @@ import javax.swing.ListCellRenderer
class KotlinLineMarkerProvider : LineMarkerProvider {
override fun getLineMarkerInfo(element: PsiElement): LineMarkerInfo<PsiElement>? {
// all Kotlin markers are added in slow marker pass
if (DaemonCodeAnalyzerSettings.getInstance().SHOW_METHOD_SEPARATORS) {
if (element.canHaveSeparator()) {
val prevSibling = element.getPrevSiblingIgnoringWhitespaceAndComments()
if (prevSibling.canHaveSeparator() &&
(element.wantsSeparator() || prevSibling?.wantsSeparator() == true)) {
return createLineSeparatorByElement(element)
}
}
}
return null
}
private fun PsiElement?.canHaveSeparator() =
this is KtFunction || this is KtClassInitializer || (this is KtProperty && !isLocal)
private fun PsiElement.wantsSeparator() = StringUtil.getLineBreakCount(text) > 0
private fun createLineSeparatorByElement(element: PsiElement): LineMarkerInfo<PsiElement> {
val anchor = PsiTreeUtil.getDeepestFirst(element)
val info = LineMarkerInfo(anchor, anchor.textRange, null, Pass.LINE_MARKERS, null, null, GutterIconRenderer.Alignment.RIGHT)
info.separatorColor = EditorColorsManager.getInstance().globalScheme.getColor(CodeInsightColors.METHOD_SEPARATORS_COLOR)
info.separatorPlacement = SeparatorPlacement.TOP
return info
}
override fun collectSlowLineMarkers(elements: List<PsiElement>, result: MutableCollection<LineMarkerInfo<*>>) {
if (elements.isEmpty()) return
@@ -0,0 +1,37 @@
// METHOD_SEPARATORS
class Foo {
object BarObj {
}
fun bar() {
}
<lineMarker descr="null">fun</lineMarker> baz() {
class FooLocal {
}
fun fooLocal() {
}
<lineMarker descr="null">fun</lineMarker> barLocal() {
}
val xLocal = run {
"x"
}
}
<lineMarker descr="null">val</lineMarker> x = 0
<lineMarker descr="null">val</lineMarker> y: Int
get() = 0
<lineMarker descr="null">val</lineMarker> z = run {
"abc"
}
<lineMarker descr="null">fun</lineMarker> quux() {}
fun xyzzy() {}
}
@@ -1,21 +1,11 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* 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.
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.codeInsight
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings
import com.intellij.codeInsight.daemon.LineMarkerInfo
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl
import com.intellij.openapi.util.io.FileUtil
@@ -33,6 +23,7 @@ import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TagsTestDataUtil
import org.jetbrains.kotlin.test.util.renderAsGotoImplementation
@@ -53,6 +44,10 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase()
val fileText = FileUtil.loadFile(File(path))
try {
ConfigLibraryUtil.configureLibrariesByDirective(myFixture.module, PlatformTestUtil.getCommunityPath(), fileText)
if (InTextDirectivesUtils.findStringWithPrefixes(fileText,"METHOD_SEPARATORS") != null) {
DaemonCodeAnalyzerSettings.getInstance().SHOW_METHOD_SEPARATORS = true
}
myFixture.configureByFile(path)
val project = myFixture.project
@@ -98,6 +93,7 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase()
}
finally {
ConfigLibraryUtil.unconfigureLibrariesByDirective(myModule, fileText)
DaemonCodeAnalyzerSettings.getInstance().SHOW_METHOD_SEPARATORS = false
}
}
@@ -25,6 +25,12 @@ public class LineMarkersTestGenerated extends AbstractLineMarkersTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/codeInsight/lineMarker"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("MethodSeparators.kt")
public void testMethodSeparators() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/lineMarker/MethodSeparators.kt");
doTest(fileName);
}
@TestMetadata("idea/testData/codeInsight/lineMarker/overrideImplement")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)