Debugger: implement Smart Step Into
#KT-4639 Fixed
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
<root>
|
||||
<item
|
||||
name='com.intellij.debugger.actions.JvmSmartStepIntoHandler java.util.List<com.intellij.debugger.actions.SmartStepTarget> findSmartStepTargets(com.intellij.debugger.SourcePosition)'>
|
||||
<annotation name='kotlin.jvm.KotlinSignature'>
|
||||
<val name="value" val=""fun findSmartStepTargets(position: SourcePosition): List<SmartStepTarget>""/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item
|
||||
name='com.intellij.debugger.actions.JvmSmartStepIntoHandler java.util.List<com.intellij.debugger.actions.SmartStepTarget> findSmartStepTargets(com.intellij.debugger.SourcePosition) 0'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
@@ -8,4 +8,10 @@
|
||||
<item name='com.intellij.util.QueryFactory com.intellij.util.Query<Result> createUniqueResultsQuery(Parameters)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='com.intellij.util.Range T getFrom()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='com.intellij.util.Range T getTo()'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
</root>
|
||||
@@ -99,6 +99,7 @@ import org.jetbrains.jet.plugin.refactoring.move.AbstractJetMoveTest
|
||||
import org.jetbrains.jet.cfg.AbstractDataFlowTest
|
||||
import org.jetbrains.jet.plugin.libraries.AbstractDecompiledTextTest
|
||||
import org.jetbrains.jet.plugin.imports.AbstractOptimizeImportsTest
|
||||
import org.jetbrains.jet.plugin.debugger.AbstractSmartStepIntoTest
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
System.setProperty("java.awt.headless", "true")
|
||||
@@ -524,6 +525,10 @@ fun main(args: Array<String>) {
|
||||
testClass(javaClass<AbstractOptimizeImportsTest>()) {
|
||||
model("editor/optimizeImports", extension = null, recursive = false)
|
||||
}
|
||||
|
||||
testClass(javaClass<AbstractSmartStepIntoTest>()) {
|
||||
model("debugger/smartStepInto")
|
||||
}
|
||||
}
|
||||
|
||||
testGroup("j2k/tests/test", "j2k/tests/testData") {
|
||||
|
||||
@@ -299,6 +299,7 @@
|
||||
id="kotlinJavaSafeDeleteDelegate"
|
||||
language="jet"
|
||||
implementationClass="org.jetbrains.jet.plugin.refactoring.safeDelete.KotlinJavaSafeDeleteDelegate"/>
|
||||
<debugger.jvmSmartStepIntoHandler implementation="org.jetbrains.jet.plugin.debugger.KotlinSmartStepIntoHandler"/>
|
||||
<debugger.positionManagerFactory implementation="org.jetbrains.jet.plugin.debugger.JetPositionManagerFactory"/>
|
||||
<codeInsight.implementMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.ImplementMethodsHandler"/>
|
||||
<codeInsight.overrideMethod language="jet" implementationClass="org.jetbrains.jet.plugin.codeInsight.OverrideMethodsHandler"/>
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.debugger
|
||||
|
||||
import com.intellij.debugger.actions.JvmSmartStepIntoHandler
|
||||
import com.intellij.debugger.SourcePosition
|
||||
import com.intellij.debugger.actions.SmartStepTarget
|
||||
import java.util.Collections
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager
|
||||
import com.intellij.debugger.actions.MethodSmartStepTarget
|
||||
import com.intellij.util.containers.OrderedSet
|
||||
import com.intellij.util.Range
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import org.jetbrains.jet.asJava.LightClassUtil
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils
|
||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.text.CharArrayUtil
|
||||
import org.jetbrains.jet.lang.psi.*
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
|
||||
|
||||
public class KotlinSmartStepIntoHandler : JvmSmartStepIntoHandler() {
|
||||
|
||||
override fun isAvailable(position: SourcePosition?) = position?.getFile() is JetFile
|
||||
|
||||
override fun findSmartStepTargets(position: SourcePosition): List<SmartStepTarget> {
|
||||
if (position.getLine() < 0) return Collections.emptyList()
|
||||
|
||||
val file = position.getFile()
|
||||
val vFile = file.getVirtualFile()
|
||||
if (vFile == null) return Collections.emptyList()
|
||||
|
||||
val doc = FileDocumentManager.getInstance()?.getDocument(vFile)
|
||||
if (doc == null) return Collections.emptyList()
|
||||
|
||||
val line = position.getLine()
|
||||
if (line >= doc.getLineCount()) return Collections.emptyList()
|
||||
|
||||
val lineStartOffset = doc.getLineStartOffset(line)
|
||||
val offsetWithoutTab = CharArrayUtil.shiftForward(doc.getCharsSequence(), lineStartOffset, " \t")
|
||||
val elementAtOffset = file.findElementAt(offsetWithoutTab)
|
||||
if (elementAtOffset == null) return Collections.emptyList()
|
||||
|
||||
val element = getTopmostElementAtOffset(elementAtOffset, lineStartOffset)
|
||||
|
||||
if (element !is JetElement) return Collections.emptyList()
|
||||
|
||||
val elementTextRange = element.getTextRange()
|
||||
if (elementTextRange == null) return Collections.emptyList()
|
||||
|
||||
val lines = Range<Int>(doc.getLineNumber(elementTextRange.getStartOffset()), doc.getLineNumber(elementTextRange.getEndOffset()))
|
||||
val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element)
|
||||
val result = OrderedSet<SmartStepTarget>()
|
||||
|
||||
// TODO support class initializers, local functions, delegated properties with specified type, setter for properties
|
||||
element.accept(object: JetTreeVisitorVoid() {
|
||||
|
||||
override fun visitFunctionLiteralExpression(expression: JetFunctionLiteralExpression) {
|
||||
// skip calls in function literals
|
||||
}
|
||||
|
||||
override fun visitObjectLiteralExpression(expression: JetObjectLiteralExpression) {
|
||||
// skip calls in object declarations
|
||||
}
|
||||
|
||||
override fun visitIfExpression(expression: JetIfExpression) {
|
||||
expression.getCondition()?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitWhileExpression(expression: JetWhileExpression) {
|
||||
expression.getCondition()?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitDoWhileExpression(expression: JetDoWhileExpression) {
|
||||
expression.getCondition()?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitForExpression(expression: JetForExpression) {
|
||||
expression.getLoopRange()?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitWhenExpression(expression: JetWhenExpression) {
|
||||
expression.getSubjectExpression()?.accept(this)
|
||||
}
|
||||
|
||||
override fun visitArrayAccessExpression(expression: JetArrayAccessExpression) {
|
||||
recordFunction(expression)
|
||||
super.visitArrayAccessExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitUnaryExpression(expression: JetUnaryExpression) {
|
||||
recordFunction(expression.getOperationReference())
|
||||
super.visitUnaryExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitBinaryExpression(expression: JetBinaryExpression) {
|
||||
recordFunction(expression.getOperationReference())
|
||||
super.visitBinaryExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitCallExpression(expression: JetCallExpression) {
|
||||
val calleeExpression = expression.getCalleeExpression()
|
||||
if (calleeExpression != null) {
|
||||
recordFunction(calleeExpression)
|
||||
}
|
||||
super.visitCallExpression(expression)
|
||||
}
|
||||
|
||||
override fun visitSimpleNameExpression(expression: JetSimpleNameExpression) {
|
||||
val resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression)
|
||||
if (resolvedCall != null) {
|
||||
val propertyDescriptor = resolvedCall.getResultingDescriptor()
|
||||
if (propertyDescriptor is PropertyDescriptor) {
|
||||
val getterDescriptor = propertyDescriptor.getGetter()
|
||||
if (getterDescriptor != null && !getterDescriptor.isDefault()) {
|
||||
val delegatedResolvedCall = bindingContext.get(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor)
|
||||
if (delegatedResolvedCall == null) {
|
||||
val getter = BindingContextUtils.callableDescriptorToDeclaration(bindingContext, getterDescriptor)
|
||||
if (getter is JetPropertyAccessor && (getter.getBodyExpression() != null || getter.getEqualsToken() != null)) {
|
||||
val psiMethod = LightClassUtil.getLightClassAccessorMethod(getter)
|
||||
if (psiMethod != null) {
|
||||
result.add(MethodSmartStepTarget(psiMethod, null, expression, false, lines))
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
val delegatedPropertyGetterDescriptor = delegatedResolvedCall.getResultingDescriptor()
|
||||
if (delegatedPropertyGetterDescriptor is CallableMemberDescriptor) {
|
||||
val function = BindingContextUtils.callableDescriptorToDeclaration(bindingContext, delegatedPropertyGetterDescriptor)
|
||||
if (function is JetNamedFunction) {
|
||||
val psiMethod = LightClassUtil.getLightClassMethod(function)
|
||||
if (psiMethod != null) {
|
||||
result.add(MethodSmartStepTarget(psiMethod, "${propertyDescriptor.getName()}.", expression, false, lines))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
super.visitSimpleNameExpression(expression)
|
||||
}
|
||||
|
||||
private fun recordFunction(expression: JetExpression) {
|
||||
val resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression)
|
||||
if (resolvedCall == null) return
|
||||
|
||||
val descriptor = resolvedCall.getResultingDescriptor()
|
||||
if (descriptor is CallableMemberDescriptor) {
|
||||
val function = BindingContextUtils.callableDescriptorToDeclaration(bindingContext, descriptor)
|
||||
if (function is JetNamedFunction) {
|
||||
val psiMethod = LightClassUtil.getLightClassMethod(function)
|
||||
if (psiMethod != null) {
|
||||
result.add(MethodSmartStepTarget(method = psiMethod, label = null,
|
||||
highlightElement = expression,
|
||||
needBreakpointRequest = false, lines = lines))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, null)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun getTopmostElementAtOffset(element: PsiElement, offset: Int): PsiElement? {
|
||||
var resultElement: PsiElement? = element
|
||||
while (resultElement?.getParent()?.getTextRange() != null &&
|
||||
resultElement?.getParent()?.getTextRange()!!.getStartOffset() >= offset) {
|
||||
resultElement = resultElement!!.getParent()
|
||||
}
|
||||
|
||||
return resultElement
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo() {
|
||||
[Ann() Ann] val a = bar()<caret>
|
||||
}
|
||||
|
||||
annotation class Ann
|
||||
|
||||
fun bar() = 1
|
||||
|
||||
// EXISTS: bar()
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
val a = A()
|
||||
<caret>a[1]
|
||||
}
|
||||
|
||||
class A {
|
||||
fun get(i: Int) = 1
|
||||
}
|
||||
|
||||
// EXISTS: get(int)
|
||||
@@ -0,0 +1,13 @@
|
||||
fun foo() {
|
||||
A().getB().f1()<caret>
|
||||
}
|
||||
|
||||
class A {
|
||||
fun getB() = B()
|
||||
}
|
||||
|
||||
class B {
|
||||
fun f1() {}
|
||||
}
|
||||
|
||||
// EXISTS: getB(), f1()
|
||||
@@ -0,0 +1,11 @@
|
||||
class A {
|
||||
fun plus(a: A) {}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
f1() + A() + A()<caret>
|
||||
}
|
||||
|
||||
fun f1() = A()
|
||||
|
||||
// EXISTS: plus(A), f1()
|
||||
@@ -0,0 +1,11 @@
|
||||
fun foo() {
|
||||
a<caret>
|
||||
}
|
||||
|
||||
val a by Delegate()
|
||||
|
||||
class Delegate {
|
||||
fun get(t: Any?, p: PropertyMetadata) = 1
|
||||
}
|
||||
|
||||
// EXISTS: a.get(Object\, PropertyMetadata)
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
<caret>do {
|
||||
f2()
|
||||
} while (f1())
|
||||
}
|
||||
|
||||
fun f1() = true
|
||||
fun f2() {}
|
||||
|
||||
// EXISTS: f1()
|
||||
@@ -0,0 +1,12 @@
|
||||
fun foo() {
|
||||
val a = A()
|
||||
a.f1(f2())<caret>
|
||||
}
|
||||
|
||||
class A {
|
||||
fun f1(): Int = 1
|
||||
}
|
||||
|
||||
fun f2() {}
|
||||
|
||||
// EXISTS: f1(), f2()
|
||||
@@ -0,0 +1,12 @@
|
||||
fun foo() {
|
||||
val a = A()
|
||||
f2(a.f1())<caret>
|
||||
}
|
||||
|
||||
class A {
|
||||
fun f1() = 1
|
||||
}
|
||||
|
||||
fun f2(i: Int) {}
|
||||
|
||||
// EXISTS: f1(), f2(int)
|
||||
@@ -0,0 +1,3 @@
|
||||
fun foo() {
|
||||
val a = 1<caret>
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fun foo() {
|
||||
val a = 1
|
||||
<caret>for (a in f1()) {
|
||||
f2()
|
||||
}
|
||||
}
|
||||
|
||||
fun f1() = 1..2
|
||||
fun f2() {}
|
||||
|
||||
// EXISTS: f1()
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
<caret>f1() {
|
||||
f2()
|
||||
}
|
||||
}
|
||||
|
||||
fun f1(f: () -> Unit) {}
|
||||
fun f2() {}
|
||||
|
||||
// EXISTS: f1(Function0<? extends Unit>)
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
<caret>if (f1()) {
|
||||
f2()
|
||||
}
|
||||
}
|
||||
|
||||
fun f1() = true
|
||||
fun f2() {}
|
||||
|
||||
// EXISTS: f1()
|
||||
@@ -0,0 +1,12 @@
|
||||
fun foo() {
|
||||
val a = A()
|
||||
f2(a f1 1)<caret>
|
||||
}
|
||||
|
||||
class A {
|
||||
fun f1(i: Int) = 1
|
||||
}
|
||||
|
||||
fun f2(i: Int) {}
|
||||
|
||||
// EXISTS: f1(int), f2(int)
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
val a = A()
|
||||
a()<caret>
|
||||
}
|
||||
|
||||
class A {
|
||||
fun invoke() {}
|
||||
}
|
||||
|
||||
// EXISTS: invoke()
|
||||
@@ -0,0 +1,12 @@
|
||||
fun foo() {
|
||||
<caret>f1(
|
||||
f2(),
|
||||
f3()
|
||||
)
|
||||
}
|
||||
|
||||
fun f1(vararg i: Int) {}
|
||||
fun f2() = 1
|
||||
fun f3() = 1
|
||||
|
||||
// EXISTS: f1(int...), f2(), f3()
|
||||
@@ -0,0 +1,15 @@
|
||||
fun foo() {
|
||||
<caret>A()
|
||||
.getB()
|
||||
.f1()
|
||||
}
|
||||
|
||||
class A {
|
||||
fun getB() = B()
|
||||
}
|
||||
|
||||
class B {
|
||||
fun f1() {}
|
||||
}
|
||||
|
||||
// EXISTS: getB(), f1()
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo() {
|
||||
<caret>val a = object {
|
||||
fun f() {
|
||||
f2()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun f2() {}
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo() {
|
||||
f1(f2())<caret>
|
||||
}
|
||||
|
||||
fun f1(i: Int) = 1
|
||||
fun f2() {}
|
||||
|
||||
// EXISTS: f1(int), f2()
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
(bar())<caret>
|
||||
}
|
||||
|
||||
fun bar() {}
|
||||
|
||||
// EXISTS: bar()
|
||||
@@ -0,0 +1,18 @@
|
||||
fun foo() {
|
||||
a + b + c + d<caret>
|
||||
}
|
||||
|
||||
val a = 1
|
||||
|
||||
val b = 1
|
||||
get
|
||||
|
||||
val c: Int
|
||||
get() = 1
|
||||
|
||||
val d: Int
|
||||
get() {
|
||||
return 1
|
||||
}
|
||||
|
||||
// EXISTS: getC(), getD()
|
||||
@@ -0,0 +1,7 @@
|
||||
fun foo() {
|
||||
bar()<caret>
|
||||
}
|
||||
|
||||
fun bar() {}
|
||||
|
||||
// EXISTS: bar()
|
||||
@@ -0,0 +1,8 @@
|
||||
fun foo() {
|
||||
<caret>f2("aaa${f1()}")
|
||||
}
|
||||
|
||||
fun f1() = "1"
|
||||
fun f2(s: String) {}
|
||||
|
||||
// EXISTS: f1(), f2(String)
|
||||
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
fun plus() {}
|
||||
fun minus() {}
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
+A() || A()-<caret>
|
||||
}
|
||||
// EXISTS: plus(), minus()
|
||||
@@ -0,0 +1,13 @@
|
||||
fun foo() {
|
||||
<caret>when (f1()) {
|
||||
true -> f2()
|
||||
else -> {
|
||||
f2()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun f1() = true
|
||||
fun f2() {}
|
||||
|
||||
// EXISTS: f1()
|
||||
@@ -0,0 +1,10 @@
|
||||
fun foo() {
|
||||
<caret>while (f1()) {
|
||||
f2()
|
||||
}
|
||||
}
|
||||
|
||||
fun f1() = true
|
||||
fun f2() {}
|
||||
|
||||
// EXISTS: f1()
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.debugger
|
||||
|
||||
import com.intellij.debugger.SourcePosition
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.debugger.actions.SmartStepTarget
|
||||
import org.jetbrains.jet.plugin.JetLightCodeInsightFixtureTestCase
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||
import org.jetbrains.jet.plugin.PluginTestCaseBase
|
||||
import com.intellij.debugger.actions.MethodSmartStepTarget
|
||||
import org.jetbrains.jet.InTextDirectivesUtils
|
||||
import com.intellij.psi.util.PsiFormatUtil
|
||||
import com.intellij.psi.PsiSubstitutor
|
||||
import com.intellij.psi.util.PsiFormatUtilBase
|
||||
|
||||
abstract class AbstractSmartStepIntoTest : JetLightCodeInsightFixtureTestCase() {
|
||||
private val fixture: JavaCodeInsightTestFixture
|
||||
get() = myFixture!!
|
||||
|
||||
protected fun doTest(path: String) {
|
||||
fixture.configureByFile(path)
|
||||
|
||||
val offset = fixture.getCaretOffset()
|
||||
val line = fixture.getDocument(fixture.getFile())!!.getLineNumber(offset)
|
||||
|
||||
val position = object: SourcePosition() {
|
||||
override fun getFile() = fixture.getFile()!!
|
||||
override fun getElementAt(): PsiElement? = throw UnsupportedOperationException()
|
||||
override fun getLine() = line
|
||||
override fun getOffset() = offset
|
||||
override fun openEditor(requestFocus: Boolean) = fixture.getEditor()
|
||||
override fun navigate(requestFocus: Boolean) {
|
||||
}
|
||||
override fun canNavigate() = false
|
||||
override fun canNavigateToSource() = false
|
||||
}
|
||||
|
||||
val actual = KotlinSmartStepIntoHandler().findSmartStepTargets(position).map { renderTarget(it) }
|
||||
|
||||
val expected = InTextDirectivesUtils.findListWithPrefixes(fixture.getFile()?.getText()!!.replace("\\,", "+++"), "// EXISTS: ").map { it.replace("+++", ",") }
|
||||
|
||||
for (actualTargetName in actual) {
|
||||
assert(expected.contains(actualTargetName), "Unexpected step into target was found: ${actualTargetName}\n${renderTableWithResults(expected, actual)}")
|
||||
}
|
||||
|
||||
for (expectedTargetName in expected) {
|
||||
assert(actual.contains(expectedTargetName), "Missed step into target: ${expectedTargetName}\n${renderTableWithResults(expected, actual)}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderTableWithResults(expected: List<String>, actual: List<String>): String {
|
||||
val sb = StringBuilder()
|
||||
|
||||
val maxExtStrSize = (expected.maxBy { it.size }?.size ?: 0) + 5
|
||||
val longerList = if (expected.size < actual.size) actual else expected
|
||||
val shorterList = if (expected.size < actual.size) expected else actual
|
||||
for ((i, element) in longerList.withIndices()) {
|
||||
sb.append(element)
|
||||
sb.append(" ".repeat(maxExtStrSize - element.size))
|
||||
if (i < shorterList.size) sb.append(shorterList[i])
|
||||
sb.append("\n")
|
||||
}
|
||||
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
private fun renderTarget(target: SmartStepTarget): String {
|
||||
val sb = StringBuilder()
|
||||
|
||||
val label = target.getLabel()
|
||||
if (label != null) {
|
||||
sb.append(label)
|
||||
}
|
||||
when (target) {
|
||||
is MethodSmartStepTarget -> {
|
||||
sb.append(PsiFormatUtil.formatMethod(
|
||||
target.getMethod(),
|
||||
PsiSubstitutor.EMPTY,
|
||||
PsiFormatUtilBase.SHOW_NAME or PsiFormatUtilBase.SHOW_PARAMETERS,
|
||||
PsiFormatUtilBase.SHOW_TYPE,
|
||||
999
|
||||
))
|
||||
}
|
||||
else -> {
|
||||
sb.append("Renderer for ${target.javaClass} should be implemented")
|
||||
}
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
override fun getTestDataPath(): String? {
|
||||
return PluginTestCaseBase.getTestDataPathBase() + "/debugger/smartStepInto"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.plugin.debugger;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jetbrains.jet.JetTestUtils;
|
||||
import org.jetbrains.jet.test.InnerTestClasses;
|
||||
import org.jetbrains.jet.test.TestMetadata;
|
||||
|
||||
import org.jetbrains.jet.plugin.debugger.AbstractSmartStepIntoTest;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("idea/testData/debugger/smartStepInto")
|
||||
public class SmartStepIntoTestGenerated extends AbstractSmartStepIntoTest {
|
||||
public void testAllFilesPresentInSmartStepInto() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/debugger/smartStepInto"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("annotation.kt")
|
||||
public void testAnnotation() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/annotation.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAccess.kt")
|
||||
public void testArrayAccess() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/arrayAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("callChain.kt")
|
||||
public void testCallChain() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/callChain.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("conventionMethod.kt")
|
||||
public void testConventionMethod() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/conventionMethod.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("delegatedPropertyGetter.kt")
|
||||
public void testDelegatedPropertyGetter() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/delegatedPropertyGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("doWhile.kt")
|
||||
public void testDoWhile() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/doWhile.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dotQualified.kt")
|
||||
public void testDotQualified() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/dotQualified.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dotQualifiedInParam.kt")
|
||||
public void testDotQualifiedInParam() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/dotQualifiedInParam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("empty.kt")
|
||||
public void testEmpty() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/empty.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("for.kt")
|
||||
public void testFor() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/for.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("funLiteral.kt")
|
||||
public void testFunLiteral() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/funLiteral.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("if.kt")
|
||||
public void testIf() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/if.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("infixCall.kt")
|
||||
public void testInfixCall() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/infixCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invoke.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/invoke.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multiline.kt")
|
||||
public void testMultiline() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/multiline.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multilineCallChain.kt")
|
||||
public void testMultilineCallChain() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/multilineCallChain.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("object.kt")
|
||||
public void testObject() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/object.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("param.kt")
|
||||
public void testParam() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/param.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("parantesized.kt")
|
||||
public void testParantesized() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/parantesized.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertyGetter.kt")
|
||||
public void testPropertyGetter() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/propertyGetter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/simple.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("stringTemplate.kt")
|
||||
public void testStringTemplate() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/stringTemplate.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unary.kt")
|
||||
public void testUnary() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/unary.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("when.kt")
|
||||
public void testWhen() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/when.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("while.kt")
|
||||
public void testWhile() throws Exception {
|
||||
doTest("idea/testData/debugger/smartStepInto/while.kt");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user