Check also drop-box content in multi-module line marker tests
Related to KT-26957
This commit is contained in:
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.highlighter.markers
|
package org.jetbrains.kotlin.idea.highlighter.markers
|
||||||
|
|
||||||
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator
|
|
||||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer
|
import com.intellij.ide.util.DefaultPsiElementCellRenderer
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
import org.jetbrains.kotlin.analyzer.ModuleInfo
|
||||||
@@ -64,19 +63,26 @@ fun getPlatformActualTooltip(declaration: KtDeclaration): String? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateToPlatformActual(e: MouseEvent?, declaration: KtDeclaration) {
|
fun KtDeclaration.allNavigatableActualDeclarations(): Set<KtDeclaration> =
|
||||||
val actualDeclarations =
|
actualsForExpected() + findMarkerBoundDeclarations().flatMap { it.actualsForExpected() }
|
||||||
declaration.actualsForExpected() + declaration.findMarkerBoundDeclarations().flatMap { it.actualsForExpected() }
|
|
||||||
if (actualDeclarations.isEmpty()) return
|
|
||||||
|
|
||||||
val renderer = object : DefaultPsiElementCellRenderer() {
|
class ActualExpectedPsiElementCellRenderer : DefaultPsiElementCellRenderer() {
|
||||||
override fun getContainerText(element: PsiElement?, name: String?) = ""
|
override fun getContainerText(element: PsiElement?, name: String?) = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KtDeclaration.navigateToActualTitle() = "Choose actual for $name"
|
||||||
|
|
||||||
|
fun KtDeclaration.navigateToActualUsagesTitle() = "Actuals for $name"
|
||||||
|
|
||||||
|
fun buildNavigateToActualDeclarationsPopup(e: MouseEvent?, element: PsiElement?): NavigationPopupDescriptor? {
|
||||||
|
return element?.markerDeclaration?.let {
|
||||||
|
val navigatableActualDeclarations = it.allNavigatableActualDeclarations()
|
||||||
|
if (navigatableActualDeclarations.isEmpty()) return null
|
||||||
|
return NavigationPopupDescriptor(
|
||||||
|
navigatableActualDeclarations,
|
||||||
|
it.navigateToActualTitle(),
|
||||||
|
it.navigateToActualUsagesTitle(),
|
||||||
|
ActualExpectedPsiElementCellRenderer()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
PsiElementListNavigator.openTargets(
|
|
||||||
e,
|
|
||||||
actualDeclarations.toTypedArray(),
|
|
||||||
"Choose actual for ${declaration.name}",
|
|
||||||
"Actuals for ${declaration.name}",
|
|
||||||
renderer
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.highlighter.markers
|
package org.jetbrains.kotlin.idea.highlighter.markers
|
||||||
|
|
||||||
import com.intellij.codeInsight.daemon.impl.PsiElementListNavigator
|
|
||||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
import org.jetbrains.kotlin.descriptors.MemberDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors
|
import org.jetbrains.kotlin.idea.caches.project.implementedDescriptors
|
||||||
@@ -38,20 +36,22 @@ fun getExpectedDeclarationTooltip(declaration: KtDeclaration): String? {
|
|||||||
return "Has declaration in common module"
|
return "Has declaration in common module"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateToExpectedDeclaration(e: MouseEvent?, declaration: KtDeclaration) {
|
fun KtDeclaration.allNavigatableExpectedDeclarations(): List<KtDeclaration> =
|
||||||
val expectedDeclarations =
|
listOfNotNull(expectedDeclarationIfAny()) + findMarkerBoundDeclarations().mapNotNull { it.expectedDeclarationIfAny() }
|
||||||
listOfNotNull(declaration.expectedDeclarationIfAny()) +
|
|
||||||
declaration.findMarkerBoundDeclarations().mapNotNull { it.expectedDeclarationIfAny() }
|
|
||||||
if (expectedDeclarations.isEmpty()) return
|
|
||||||
|
|
||||||
val renderer = object : DefaultPsiElementCellRenderer() {
|
fun KtDeclaration.navigateToExpectedTitle() = "Choose expected for $name"
|
||||||
override fun getContainerText(element: PsiElement?, name: String?) = ""
|
|
||||||
|
fun KtDeclaration.navigateToExpectedUsagesTitle() = "Expected for $name"
|
||||||
|
|
||||||
|
fun buildNavigateToExpectedDeclarationsPopup(e: MouseEvent?, element: PsiElement?): NavigationPopupDescriptor? {
|
||||||
|
return element?.markerDeclaration?.let {
|
||||||
|
val navigatableExpectedDeclarations = it.allNavigatableExpectedDeclarations()
|
||||||
|
if (navigatableExpectedDeclarations.isEmpty()) return null
|
||||||
|
return NavigationPopupDescriptor(
|
||||||
|
navigatableExpectedDeclarations,
|
||||||
|
it.navigateToExpectedTitle(),
|
||||||
|
it.navigateToExpectedUsagesTitle(),
|
||||||
|
ActualExpectedPsiElementCellRenderer()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
PsiElementListNavigator.openTargets(
|
|
||||||
e,
|
|
||||||
expectedDeclarations.toTypedArray(),
|
|
||||||
"Choose expected for ${declaration.name}",
|
|
||||||
"Expected for ${declaration.name}",
|
|
||||||
renderer
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
@@ -198,28 +198,52 @@ private val OVERRIDDEN_PROPERTY = object : MarkerType(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val PsiElement.markerDeclaration
|
val PsiElement.markerDeclaration
|
||||||
get() = (this as? KtDeclaration) ?: (parent as? KtDeclaration)
|
get() = (this as? KtDeclaration) ?: (parent as? KtDeclaration)
|
||||||
|
|
||||||
private val PLATFORM_ACTUAL = MarkerType(
|
private val PLATFORM_ACTUAL = object : MarkerType(
|
||||||
"PLATFORM_ACTUAL",
|
"PLATFORM_ACTUAL",
|
||||||
{ element -> element?.markerDeclaration?.let { getPlatformActualTooltip(it) } },
|
{ element -> element?.markerDeclaration?.let { getPlatformActualTooltip(it) } },
|
||||||
object : LineMarkerNavigator() {
|
object : LineMarkerNavigator() {
|
||||||
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
||||||
element?.markerDeclaration?.let { navigateToPlatformActual(e, it) }
|
buildNavigateToActualDeclarationsPopup(e, element)?.showPopup(e)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
override fun getNavigationHandler(): GutterIconNavigationHandler<PsiElement> {
|
||||||
|
val superHandler = super.getNavigationHandler()
|
||||||
|
return object : GutterIconNavigationHandler<PsiElement>, TestableLineMarkerNavigator {
|
||||||
|
override fun navigate(e: MouseEvent?, elt: PsiElement?) {
|
||||||
|
superHandler.navigate(e, elt)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTargetsPopupDescriptor(element: PsiElement?): NavigationPopupDescriptor? {
|
||||||
|
return buildNavigateToActualDeclarationsPopup(null, element)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
private val EXPECTED_DECLARATION = MarkerType(
|
private val EXPECTED_DECLARATION = object : MarkerType(
|
||||||
"EXPECTED_DECLARATION",
|
"EXPECTED_DECLARATION",
|
||||||
{ element -> element?.markerDeclaration?.let { getExpectedDeclarationTooltip(it) } },
|
{ element -> element?.markerDeclaration?.let { getExpectedDeclarationTooltip(it) } },
|
||||||
object : LineMarkerNavigator() {
|
object : LineMarkerNavigator() {
|
||||||
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
override fun browse(e: MouseEvent?, element: PsiElement?) {
|
||||||
element?.markerDeclaration?.let { navigateToExpectedDeclaration(e, it) }
|
buildNavigateToExpectedDeclarationsPopup(e, element)?.showPopup(e)
|
||||||
|
}
|
||||||
|
}) {
|
||||||
|
override fun getNavigationHandler(): GutterIconNavigationHandler<PsiElement> {
|
||||||
|
val superHandler = super.getNavigationHandler()
|
||||||
|
return object : GutterIconNavigationHandler<PsiElement>, TestableLineMarkerNavigator {
|
||||||
|
override fun navigate(e: MouseEvent?, elt: PsiElement?) {
|
||||||
|
superHandler.navigate(e, elt)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTargetsPopupDescriptor(element: PsiElement?): NavigationPopupDescriptor? {
|
||||||
|
return buildNavigateToExpectedDeclarationsPopup(null, element)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
private fun isImplementsAndNotOverrides(
|
private fun isImplementsAndNotOverrides(
|
||||||
descriptor: CallableMemberDescriptor,
|
descriptor: CallableMemberDescriptor,
|
||||||
|
|||||||
+11
-1
@@ -1 +1,11 @@
|
|||||||
actual class <lineMarker>WithConstructor</lineMarker> actual constructor(actual val x: Int, actual val s: String)
|
actual class <lineMarker descr="Has declaration in common module">WithConstructor</lineMarker> actual constructor(actual val x: Int, actual val s: String)
|
||||||
|
|
||||||
|
/*
|
||||||
|
LINEMARKER: Has declaration in common module
|
||||||
|
TARGETS:
|
||||||
|
common.kt
|
||||||
|
expect class <1>WithConstructor(x: Int, s: String) {
|
||||||
|
val <3>x: Int
|
||||||
|
|
||||||
|
val <2>s: String
|
||||||
|
*/
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
actual enum class <lineMarker>Enum</lineMarker> { A, B, C }
|
actual enum class <lineMarker descr="Has declaration in common module">Enum</lineMarker> { A, B, C }
|
||||||
|
|
||||||
|
/*
|
||||||
|
LINEMARKER: Has declaration in common module
|
||||||
|
TARGETS:
|
||||||
|
common.kt
|
||||||
|
expect enum class <4>Enum { <1>A, <2>B, <3>C }
|
||||||
|
*/
|
||||||
|
|||||||
+8
-1
@@ -1,3 +1,10 @@
|
|||||||
package test
|
package test
|
||||||
|
|
||||||
expect enum class <lineMarker>Enum</lineMarker> { A, B, C, D }
|
expect enum class <lineMarker descr="Has actuals in JVM">Enum</lineMarker> { A, B, C, D }
|
||||||
|
|
||||||
|
/*
|
||||||
|
LINEMARKER: Has actuals in JVM
|
||||||
|
TARGETS:
|
||||||
|
jvm.kt
|
||||||
|
actual enum class <5>Enum { <1>A, <2>B, <3>C, <4>D }
|
||||||
|
*/
|
||||||
|
|||||||
+10
-1
@@ -1,3 +1,12 @@
|
|||||||
interface <lineMarker>I</lineMarker> {
|
interface <lineMarker>I</lineMarker> {
|
||||||
suspend fun <lineMarker descr="<html><body>Is implemented in <br> KJs<br> KJvm</body></html>">foo</lineMarker>(s: String)
|
suspend fun <lineMarker descr="<html><body>Is implemented in <br> KJs<br> KJvm</body></html>">foo</lineMarker>(s: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
LINEMARKER: <html><body>Is implemented in <br> KJs<br> KJvm</body></html>
|
||||||
|
TARGETS:
|
||||||
|
js.kt
|
||||||
|
suspend override fun <1>foo(s: String) {
|
||||||
|
jvm.kt
|
||||||
|
suspend override fun <2>foo(s: String) {
|
||||||
|
*/
|
||||||
|
|||||||
+14
@@ -16,16 +16,30 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.caches.resolve
|
package org.jetbrains.kotlin.idea.caches.resolve
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.AbstractLineMarkersTest
|
||||||
import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromDirStructure
|
import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromDirStructure
|
||||||
import org.jetbrains.kotlin.idea.stubs.AbstractMultiHighlightingTest
|
import org.jetbrains.kotlin.idea.stubs.AbstractMultiHighlightingTest
|
||||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||||
import org.jetbrains.kotlin.idea.test.allJavaFiles
|
import org.jetbrains.kotlin.idea.test.allJavaFiles
|
||||||
import org.jetbrains.kotlin.idea.test.allKotlinFiles
|
import org.jetbrains.kotlin.idea.test.allKotlinFiles
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class AbstractMultiModuleHighlightingTest : AbstractMultiHighlightingTest() {
|
abstract class AbstractMultiModuleHighlightingTest : AbstractMultiHighlightingTest() {
|
||||||
|
|
||||||
|
protected open fun checkLineMarkersInProject(
|
||||||
|
findFiles: () -> List<PsiFile> = { project.allKotlinFiles().excludeByDirective() }
|
||||||
|
) {
|
||||||
|
checkFiles(findFiles) {
|
||||||
|
checkHighlighting(myEditor, true, false)
|
||||||
|
|
||||||
|
val markers = DaemonCodeAnalyzerImpl.getLineMarkers(getDocument(file), project)
|
||||||
|
AbstractLineMarkersTest.assertNavigationElements(project, myFile as KtFile, markers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected open fun checkHighlightingInProject(
|
protected open fun checkHighlightingInProject(
|
||||||
findFiles: () -> List<PsiFile> = { project.allKotlinFiles().excludeByDirective() }
|
findFiles: () -> List<PsiFile> = { project.allKotlinFiles().excludeByDirective() }
|
||||||
) {
|
) {
|
||||||
|
|||||||
+1
-1
@@ -32,6 +32,6 @@ abstract class AbstractMultiModuleLineMarkerTest : AbstractMultiModuleHighlighti
|
|||||||
|
|
||||||
protected fun doTest(path: String) {
|
protected fun doTest(path: String) {
|
||||||
setupMppProjectFromDirStructure(File(path))
|
setupMppProjectFromDirStructure(File(path))
|
||||||
checkHighlightingInProject()
|
checkLineMarkersInProject()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings
|
|||||||
import com.intellij.codeInsight.daemon.LineMarkerInfo
|
import com.intellij.codeInsight.daemon.LineMarkerInfo
|
||||||
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl
|
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl
|
||||||
import com.intellij.openapi.editor.Document
|
import com.intellij.openapi.editor.Document
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.psi.PsiDocumentManager
|
import com.intellij.psi.PsiDocumentManager
|
||||||
import com.intellij.rt.execution.junit.FileComparisonFailure
|
import com.intellij.rt.execution.junit.FileComparisonFailure
|
||||||
@@ -93,7 +94,7 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase()
|
|||||||
|
|
||||||
val markers = doAndCheckHighlighting(document, data, File(path))
|
val markers = doAndCheckHighlighting(document, data, File(path))
|
||||||
|
|
||||||
assertNavigationElements(markers)
|
assertNavigationElements(myFixture.project, myFixture.file as KtFile, markers)
|
||||||
additionalCheck()
|
additionalCheck()
|
||||||
} catch (exc: Exception) {
|
} catch (exc: Exception) {
|
||||||
throw RuntimeException(exc)
|
throw RuntimeException(exc)
|
||||||
@@ -104,45 +105,53 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assertNavigationElements(markers: List<LineMarkerInfo<*>>) {
|
|
||||||
val navigationDataComments = KotlinTestUtils.getLastCommentsInFile(
|
|
||||||
myFixture.file as KtFile, KotlinTestUtils.CommentType.BLOCK_COMMENT, false)
|
|
||||||
if (navigationDataComments.isEmpty()) return
|
|
||||||
|
|
||||||
for (navigationComment in navigationDataComments) {
|
|
||||||
val description = getLineMarkerDescription(navigationComment)
|
|
||||||
val navigateMarker = markers.find { it.lineMarkerTooltip?.startsWith(description) == true }!!
|
|
||||||
|
|
||||||
TestCase.assertNotNull(
|
|
||||||
String.format("Can't find marker for navigation check with description \"%s\"", description),
|
|
||||||
navigateMarker)
|
|
||||||
|
|
||||||
val handler = navigateMarker.navigationHandler
|
|
||||||
if (handler is TestableLineMarkerNavigator) {
|
|
||||||
val navigateElements = handler.getTargetsPopupDescriptor(navigateMarker.element)?.targets?.sortedBy { it.renderAsGotoImplementation() }
|
|
||||||
val actualNavigationData = NavigationTestUtils.getNavigateElementsText(myFixture.project, navigateElements)
|
|
||||||
|
|
||||||
UsefulTestCase.assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Assert.fail("Only SuperDeclarationMarkerNavigationHandler are supported in navigate check")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private val LINE_MARKER_PREFIX = "LINEMARKER:"
|
@Suppress("SpellCheckingInspection")
|
||||||
private val TARGETS_PREFIX = "TARGETS"
|
private const val LINE_MARKER_PREFIX = "LINEMARKER:"
|
||||||
|
private const val TARGETS_PREFIX = "TARGETS"
|
||||||
|
|
||||||
|
fun assertNavigationElements(project: Project, file: KtFile, markers: List<LineMarkerInfo<*>>) {
|
||||||
|
val navigationDataComments = KotlinTestUtils.getLastCommentsInFile(
|
||||||
|
file, KotlinTestUtils.CommentType.BLOCK_COMMENT, false
|
||||||
|
)
|
||||||
|
if (navigationDataComments.isEmpty()) return
|
||||||
|
|
||||||
|
for (navigationComment in navigationDataComments) {
|
||||||
|
val description = getLineMarkerDescription(navigationComment)
|
||||||
|
val navigateMarker = markers.find { it.lineMarkerTooltip?.startsWith(description) == true }!!
|
||||||
|
|
||||||
|
TestCase.assertNotNull(
|
||||||
|
String.format("Can't find marker for navigation check with description \"%s\"", description),
|
||||||
|
navigateMarker
|
||||||
|
)
|
||||||
|
|
||||||
|
val handler = navigateMarker.navigationHandler
|
||||||
|
if (handler is TestableLineMarkerNavigator) {
|
||||||
|
val navigateElements = handler.getTargetsPopupDescriptor(navigateMarker.element)?.targets?.sortedBy {
|
||||||
|
it.renderAsGotoImplementation()
|
||||||
|
}
|
||||||
|
val actualNavigationData = NavigationTestUtils.getNavigateElementsText(project, navigateElements)
|
||||||
|
|
||||||
|
UsefulTestCase.assertSameLines(getExpectedNavigationText(navigationComment), actualNavigationData)
|
||||||
|
} else {
|
||||||
|
Assert.fail("Only TestableLineMarkerNavigator are supported in navigate check")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getLineMarkerDescription(navigationComment: String): String {
|
private fun getLineMarkerDescription(navigationComment: String): String {
|
||||||
val firstLineEnd = navigationComment.indexOf("\n")
|
val firstLineEnd = navigationComment.indexOf("\n")
|
||||||
TestCase.assertTrue("The first line in block comment must contain description of marker for navigation check", firstLineEnd != -1)
|
TestCase.assertTrue(
|
||||||
|
"The first line in block comment must contain description of marker for navigation check", firstLineEnd != -1
|
||||||
|
)
|
||||||
|
|
||||||
var navigationMarkerText = navigationComment.substring(0, firstLineEnd)
|
var navigationMarkerText = navigationComment.substring(0, firstLineEnd)
|
||||||
|
|
||||||
TestCase.assertTrue(String.format("Add %s directive in first line of comment", LINE_MARKER_PREFIX),
|
TestCase.assertTrue(
|
||||||
navigationMarkerText.startsWith(LINE_MARKER_PREFIX))
|
String.format("Add %s directive in first line of comment", LINE_MARKER_PREFIX),
|
||||||
|
navigationMarkerText.startsWith(LINE_MARKER_PREFIX)
|
||||||
|
)
|
||||||
|
|
||||||
navigationMarkerText = navigationMarkerText.substring(LINE_MARKER_PREFIX.length)
|
navigationMarkerText = navigationMarkerText.substring(LINE_MARKER_PREFIX.length)
|
||||||
|
|
||||||
@@ -155,8 +164,9 @@ abstract class AbstractLineMarkersTest : KotlinLightCodeInsightFixtureTestCase()
|
|||||||
var expectedNavigationText = navigationComment.substring(firstLineEnd + 1)
|
var expectedNavigationText = navigationComment.substring(firstLineEnd + 1)
|
||||||
|
|
||||||
TestCase.assertTrue(
|
TestCase.assertTrue(
|
||||||
String.format("Marker %s is expected before navigation data", TARGETS_PREFIX),
|
String.format("Marker %s is expected before navigation data", TARGETS_PREFIX),
|
||||||
expectedNavigationText.startsWith(TARGETS_PREFIX))
|
expectedNavigationText.startsWith(TARGETS_PREFIX)
|
||||||
|
)
|
||||||
|
|
||||||
expectedNavigationText = expectedNavigationText.substring(expectedNavigationText.indexOf("\n") + 1)
|
expectedNavigationText = expectedNavigationText.substring(expectedNavigationText.indexOf("\n") + 1)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user