Test it's safe to call PsiElement methods on Kotlin light elements
This commit is contained in:
committed by
Nikolay Krasko
parent
7c752c1463
commit
178aba54dd
+2
@@ -27,4 +27,6 @@ public class KotlinLightTypeParameterListBuilder(manager: PsiManager): LightType
|
|||||||
override fun processDeclarations(processor: PsiScopeProcessor, state: ResolveState, lastParent: PsiElement?, place: PsiElement): Boolean {
|
override fun processDeclarations(processor: PsiScopeProcessor, state: ResolveState, lastParent: PsiElement?, place: PsiElement): Boolean {
|
||||||
return getTypeParameters().all { processor.execute(it, state) }
|
return getTypeParameters().all { processor.execute(it, state) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getText(): String? = ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,9 +69,9 @@ sealed class KtLightFieldImpl(
|
|||||||
|
|
||||||
override fun hasModifierProperty(@NonNls name: String) = delegate.hasModifierProperty(name)
|
override fun hasModifierProperty(@NonNls name: String) = delegate.hasModifierProperty(name)
|
||||||
|
|
||||||
override fun getText() = delegate.text
|
override fun getText() = origin?.text ?: ""
|
||||||
|
|
||||||
override fun getTextRange() = TextRange(-1, -1)
|
override fun getTextRange() = origin?.textRange ?: TextRange.EMPTY_RANGE
|
||||||
|
|
||||||
override fun isValid() = containingClass.isValid
|
override fun isValid() = containingClass.isValid
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ sealed class KtLightFieldImpl(
|
|||||||
override fun getDelegate() = delegate
|
override fun getDelegate() = delegate
|
||||||
|
|
||||||
override fun getNavigationElement() = origin ?: super.getNavigationElement()
|
override fun getNavigationElement() = origin ?: super.getNavigationElement()
|
||||||
|
|
||||||
override fun isEquivalentTo(another: PsiElement?): Boolean {
|
override fun isEquivalentTo(another: PsiElement?): Boolean {
|
||||||
if (another is KtLightField && origin == another.getOrigin() && delegate == another.getDelegate()) {
|
if (another is KtLightField && origin == another.getOrigin() && delegate == another.getDelegate()) {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.asJava
|
package org.jetbrains.kotlin.asJava
|
||||||
|
|
||||||
import com.intellij.core.JavaCoreBundle
|
import com.intellij.core.JavaCoreBundle
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.light.LightMethod
|
import com.intellij.psi.impl.light.LightMethod
|
||||||
import com.intellij.psi.scope.PsiScopeProcessor
|
import com.intellij.psi.scope.PsiScopeProcessor
|
||||||
@@ -68,6 +69,8 @@ sealed class KtLightMethodImpl(
|
|||||||
override fun getDelegate() = delegate
|
override fun getDelegate() = delegate
|
||||||
override fun getOrigin() = origin
|
override fun getOrigin() = origin
|
||||||
override fun getParent(): PsiElement? = containingClass
|
override fun getParent(): PsiElement? = containingClass
|
||||||
|
override fun getText() = origin?.text ?: ""
|
||||||
|
override fun getTextRange() = origin?.textRange ?: TextRange.EMPTY_RANGE
|
||||||
|
|
||||||
override fun accept(visitor: PsiElementVisitor) {
|
override fun accept(visitor: PsiElementVisitor) {
|
||||||
if (visitor is JavaElementVisitor) {
|
if (visitor is JavaElementVisitor) {
|
||||||
@@ -140,7 +143,7 @@ sealed class KtLightMethodImpl(
|
|||||||
override fun hashCode(): Int = ((name.hashCode() * 31 + (origin?.hashCode() ?: 0)) * 31 + containingClass.hashCode()) * 31 + delegate.hashCode()
|
override fun hashCode(): Int = ((name.hashCode() * 31 + (origin?.hashCode() ?: 0)) * 31 + containingClass.hashCode()) * 31 + delegate.hashCode()
|
||||||
|
|
||||||
override fun toString(): String = "${this.javaClass.simpleName}:$name"
|
override fun toString(): String = "${this.javaClass.simpleName}:$name"
|
||||||
|
|
||||||
private class KtLightMethodForDeclaration(
|
private class KtLightMethodForDeclaration(
|
||||||
delegate: PsiMethod, origin: KtDeclaration?, containingClass: KtLightClass
|
delegate: PsiMethod, origin: KtDeclaration?, containingClass: KtLightClass
|
||||||
) : KtLightMethodImpl(delegate, origin, containingClass)
|
) : KtLightMethodImpl(delegate, origin, containingClass)
|
||||||
|
|||||||
@@ -135,4 +135,9 @@ public class KtLightParameter extends LightParameter implements KtLightElement<K
|
|||||||
public KtLightMethod getMethod() {
|
public KtLightMethod getMethod() {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,11 @@ public class KtLightTypeParameter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ public abstract class KtWrappingLightClass extends AbstractLightClass implements
|
|||||||
@Override
|
@Override
|
||||||
public String getText() {
|
public String getText() {
|
||||||
KtClassOrObject origin = getOrigin();
|
KtClassOrObject origin = getOrigin();
|
||||||
return origin == null ? null : origin.getText();
|
return origin == null ? "" : origin.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescrip
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
abstract class AbstractIdeLightClassTest : KotlinLightCodeInsightFixtureTestCase() {
|
abstract class AbstractIdeLightClassTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||||
|
|
||||||
fun doTest(testDataPath: String) {
|
fun doTest(testDataPath: String) {
|
||||||
myFixture.configureByFile(testDataPath)
|
myFixture.configureByFile(testDataPath)
|
||||||
|
|
||||||
@@ -32,15 +31,23 @@ abstract class AbstractIdeLightClassTest : KotlinLightCodeInsightFixtureTestCase
|
|||||||
LightClassTestCommon.testLightClass(
|
LightClassTestCommon.testLightClass(
|
||||||
File(testDataPath),
|
File(testDataPath),
|
||||||
findLightClass = {
|
findLightClass = {
|
||||||
JavaPsiFacade.getInstance(project).findClass(it, GlobalSearchScope.allScope(project))
|
val clazz = JavaPsiFacade.getInstance(project).findClass(it, GlobalSearchScope.allScope(project))
|
||||||
|
if (clazz != null) {
|
||||||
|
PsiElementChecker.checkPsiElementStructure(clazz)
|
||||||
|
}
|
||||||
|
clazz
|
||||||
|
|
||||||
},
|
},
|
||||||
normalizeText = {
|
normalizeText = {
|
||||||
//NOTE: ide and compiler differ in names generated for parameters with unspecified names
|
//NOTE: ide and compiler differ in names generated for parameters with unspecified names
|
||||||
it.replace("java.lang.String s,", "java.lang.String p,").replace("java.lang.String s)", "java.lang.String p)")
|
it
|
||||||
.replace("java.lang.String s1", "java.lang.String p1").replace("java.lang.String s2", "java.lang.String p2")
|
.replace("java.lang.String s,", "java.lang.String p,")
|
||||||
|
.replace("java.lang.String s)", "java.lang.String p)")
|
||||||
|
.replace("java.lang.String s1", "java.lang.String p1")
|
||||||
|
.replace("java.lang.String s2", "java.lang.String p2")
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.caches.resolve;
|
||||||
|
|
||||||
|
public class AssertionErrorWithCause extends AssertionError {
|
||||||
|
public AssertionErrorWithCause(String detailMessage, Throwable cause) {
|
||||||
|
super(detailMessage);
|
||||||
|
|
||||||
|
initCause(cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.caches.resolve
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.Key
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import org.jetbrains.kotlin.asJava.KtLightElement
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
|
import org.junit.Assert
|
||||||
|
|
||||||
|
object PsiElementChecker {
|
||||||
|
val TEST_DATA_KEY = Key.create<Int>("Test Key")
|
||||||
|
|
||||||
|
public fun checkPsiElementStructure(lightClass: PsiClass) {
|
||||||
|
checkPsiElement(lightClass)
|
||||||
|
|
||||||
|
lightClass.innerClasses.forEach { checkPsiElementStructure(it) }
|
||||||
|
|
||||||
|
lightClass.methods.forEach {
|
||||||
|
it.parameterList.parameters.forEach { checkPsiElement(it) }
|
||||||
|
checkPsiElement(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
lightClass.fields.forEach { checkPsiElement(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkPsiElement(element: PsiElement) {
|
||||||
|
if (element !is KtLightElement<*, *>) return
|
||||||
|
|
||||||
|
if (element is PsiModifierListOwner) {
|
||||||
|
val modifierList = element.modifierList
|
||||||
|
if (modifierList != null) {
|
||||||
|
checkPsiElement(modifierList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element is PsiTypeParameterListOwner) {
|
||||||
|
val typeParameterList = element.typeParameterList
|
||||||
|
if (typeParameterList != null) {
|
||||||
|
checkPsiElement(typeParameterList)
|
||||||
|
typeParameterList.typeParameters.forEach { checkPsiElement(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
with(element) {
|
||||||
|
try {
|
||||||
|
Assert.assertEquals("Number of methods has changed. Please update test.", 54, PsiElement::class.java.methods.size)
|
||||||
|
|
||||||
|
project
|
||||||
|
Assert.assertTrue(language == KotlinLanguage.INSTANCE)
|
||||||
|
manager
|
||||||
|
children
|
||||||
|
parent
|
||||||
|
firstChild
|
||||||
|
lastChild
|
||||||
|
nextSibling
|
||||||
|
prevSibling
|
||||||
|
containingFile
|
||||||
|
textRange
|
||||||
|
startOffsetInParent
|
||||||
|
textLength
|
||||||
|
findElementAt(0)
|
||||||
|
findReferenceAt(0)
|
||||||
|
textOffset
|
||||||
|
text
|
||||||
|
textToCharArray()
|
||||||
|
navigationElement
|
||||||
|
originalElement
|
||||||
|
textMatches("")
|
||||||
|
Assert.assertTrue(textMatches(this))
|
||||||
|
textContains('a')
|
||||||
|
accept(PsiElementVisitor.EMPTY_VISITOR)
|
||||||
|
acceptChildren(PsiElementVisitor.EMPTY_VISITOR)
|
||||||
|
|
||||||
|
val copy = copy()
|
||||||
|
Assert.assertTrue(copy == null || copy.javaClass == this.javaClass)
|
||||||
|
|
||||||
|
// Modify methods:
|
||||||
|
// add(this)
|
||||||
|
// addBefore(this, lastChild)
|
||||||
|
// addAfter(firstChild, this)
|
||||||
|
// checkAdd(this)
|
||||||
|
// addRange(firstChild, lastChild)
|
||||||
|
// addRangeBefore(firstChild, lastChild, lastChild)
|
||||||
|
// addRangeAfter(firstChild, lastChild, firstChild)
|
||||||
|
// delete()
|
||||||
|
// checkDelete()
|
||||||
|
// deleteChildRange(firstChild, lastChild)
|
||||||
|
// replace(this)
|
||||||
|
|
||||||
|
Assert.assertTrue(isValid)
|
||||||
|
isWritable
|
||||||
|
reference
|
||||||
|
references
|
||||||
|
putCopyableUserData(TEST_DATA_KEY, 12)
|
||||||
|
|
||||||
|
Assert.assertTrue(getCopyableUserData(TEST_DATA_KEY) == 12)
|
||||||
|
// Assert.assertTrue(copy().getCopyableUserData(TEST_DATA_KEY) == 12) { this } Doesn't work
|
||||||
|
|
||||||
|
// processDeclarations(...)
|
||||||
|
|
||||||
|
context
|
||||||
|
isPhysical
|
||||||
|
resolveScope
|
||||||
|
useScope
|
||||||
|
node
|
||||||
|
toString()
|
||||||
|
Assert.assertTrue(isEquivalentTo(this))
|
||||||
|
}
|
||||||
|
catch (t: Throwable) {
|
||||||
|
throw AssertionErrorWithCause("Failed for ${this.javaClass} ${this}", t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user