Tests: Introduce LightClassComputationControl to track when stubs for light classes are built
Use it to track when light classes are built in KotlinSourceInJavaCompletionTest
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.asJava
|
package org.jetbrains.kotlin.asJava
|
||||||
|
|
||||||
import com.google.common.collect.Lists
|
import com.google.common.collect.Lists
|
||||||
|
import com.intellij.openapi.components.ServiceManager
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
import com.intellij.openapi.progress.ProcessCanceledException
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
@@ -107,6 +108,8 @@ abstract class LightClassDataProvider<T : WithFileStubAndExtraDiagnostics>(
|
|||||||
if (pop !== javaFileStub) {
|
if (pop !== javaFileStub) {
|
||||||
LOG.error("Unbalanced stack operations: " + pop)
|
LOG.error("Unbalanced stack operations: " + pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ServiceManager.getService(project, StubComputationTracker::class.java)?.onStubComputed(javaFileStub)
|
||||||
}
|
}
|
||||||
catch (e: ProcessCanceledException) {
|
catch (e: ProcessCanceledException) {
|
||||||
throw e
|
throw e
|
||||||
@@ -354,3 +357,8 @@ class LightClassDataProviderForFileFacade(
|
|||||||
return this.javaClass.name + " for $facadeFqName"
|
return this.javaClass.name + " for $facadeFqName"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface StubComputationTracker {
|
||||||
|
fun onStubComputed(javaFileStub: PsiJavaFileStub)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ public class Testing {
|
|||||||
|
|
||||||
// EXIST: c
|
// EXIST: c
|
||||||
// EXIST: d
|
// EXIST: d
|
||||||
|
// LIGHT_CLASS: mockLib.foo.Anno
|
||||||
@@ -5,3 +5,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: foo
|
// EXIST: foo
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibClass
|
||||||
+2
-1
@@ -4,4 +4,5 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: classObjectFun
|
// EXIST: classObjectFun
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibClass
|
||||||
@@ -5,3 +5,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: Companion
|
// EXIST: Companion
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibClass
|
||||||
@@ -5,3 +5,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: RED, GREEN, BLUE
|
// EXIST: RED, GREEN, BLUE
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibEnum
|
||||||
@@ -5,3 +5,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: DefaultImpls
|
// EXIST: DefaultImpls
|
||||||
|
// LIGHT_CLASS: mockLib.foo.MyInterface
|
||||||
@@ -6,3 +6,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: foo
|
// EXIST: foo
|
||||||
|
// LIGHT_CLASS: mockLib.foo.MyInterface
|
||||||
@@ -5,3 +5,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: foo
|
// EXIST: foo
|
||||||
|
// LIGHT_CLASS: mockLib.foo.MyInterface
|
||||||
+1
@@ -6,3 +6,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: foo
|
// EXIST: foo
|
||||||
|
// LIGHT_CLASS: mockLib.foo.MyInterface
|
||||||
@@ -6,4 +6,4 @@ public class Testing {
|
|||||||
|
|
||||||
// EXIST: funInFacade
|
// EXIST: funInFacade
|
||||||
// EXIST: funInFacade2
|
// EXIST: funInFacade2
|
||||||
|
// LIGHT_CLASS: facades.MultiFileFacadeClass
|
||||||
@@ -7,3 +7,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: LibClass.Nested
|
// EXIST: LibClass.Nested
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibClass
|
||||||
@@ -6,3 +6,4 @@ public class Testing {
|
|||||||
|
|
||||||
// EXIST: getValInNested
|
// EXIST: getValInNested
|
||||||
// EXIST: funInNested
|
// EXIST: funInNested
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibClass
|
||||||
@@ -6,3 +6,4 @@ public class Testing {
|
|||||||
|
|
||||||
// EXIST: getValInNested
|
// EXIST: getValInNested
|
||||||
// EXIST: funInNested
|
// EXIST: funInNested
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibClass
|
||||||
@@ -5,3 +5,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: INSTANCE
|
// EXIST: INSTANCE
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibClass
|
||||||
@@ -4,3 +4,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: F
|
// EXIST: F
|
||||||
|
// LIGHT_CLASS: mockLib.foo.F
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: INSTANCE
|
// EXIST: INSTANCE
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibObject
|
||||||
@@ -8,4 +8,4 @@ public class Testing {
|
|||||||
// EXIST: topLevelExtFunction
|
// EXIST: topLevelExtFunction
|
||||||
// EXIST: getTopLevelVar
|
// EXIST: getTopLevelVar
|
||||||
// EXIST: setTopLevelVar
|
// EXIST: setTopLevelVar
|
||||||
|
// LIGHT_CLASS: mockLib.foo.MainKt
|
||||||
|
|||||||
@@ -7,3 +7,4 @@ public class Testing {
|
|||||||
// EXIST: topLevelFunction
|
// EXIST: topLevelFunction
|
||||||
// EXIST: topLevelExtFunction
|
// EXIST: topLevelExtFunction
|
||||||
// EXIST: getTopLevelVar, setTopLevelVar
|
// EXIST: getTopLevelVar, setTopLevelVar
|
||||||
|
// LIGHT_CLASS: mockLib.foo.MainKt
|
||||||
+1
-1
@@ -5,4 +5,4 @@ public class Testing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST: foo
|
// EXIST: foo
|
||||||
|
// LIGHT_CLASS: mockLib.foo.LibTrait
|
||||||
+8
-13
@@ -19,10 +19,6 @@ package org.jetbrains.kotlin.idea.completion.test
|
|||||||
import com.intellij.codeInsight.completion.CompletionType
|
import com.intellij.codeInsight.completion.CompletionType
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||||
import com.intellij.util.ArrayUtil
|
|
||||||
import com.intellij.util.Function
|
|
||||||
import com.intellij.util.containers.ContainerUtil
|
|
||||||
import junit.framework.TestCase
|
|
||||||
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -31,17 +27,16 @@ public abstract class AbstractKotlinSourceInJavaCompletionTest : KotlinFixtureCo
|
|||||||
|
|
||||||
override fun doTest(testPath: String) {
|
override fun doTest(testPath: String) {
|
||||||
val mockLibDir = File(COMPLETION_TEST_DATA_BASE_PATH + "/injava/mockLib")
|
val mockLibDir = File(COMPLETION_TEST_DATA_BASE_PATH + "/injava/mockLib")
|
||||||
val listFiles = mockLibDir.listFiles()
|
val paths = mockLibDir.listFiles()!!.map {
|
||||||
TestCase.assertNotNull(listFiles)
|
FileUtil.toSystemIndependentName(it.absolutePath)
|
||||||
val paths = ArrayUtil.toStringArray(ContainerUtil.map<File, String>(listFiles, object : Function<File, String> {
|
}.toTypedArray()
|
||||||
override fun `fun`(file: File): String {
|
|
||||||
return FileUtil.toSystemIndependentName(file.getAbsolutePath())
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
myFixture.configureByFiles(*paths)
|
myFixture.configureByFiles(*paths)
|
||||||
super.doTest(testPath)
|
LightClassComputationControl.testWithControl(project, FileUtil.loadFile(File(testPath))) {
|
||||||
|
super.doTest(testPath)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getProjectDescriptor() = LightCodeInsightFixtureTestCase.JAVA_LATEST
|
override fun getProjectDescriptor() = LightCodeInsightFixtureTestCase.JAVA_LATEST
|
||||||
override fun defaultCompletionType() = CompletionType.BASIC
|
override fun defaultCompletionType() = CompletionType.BASIC
|
||||||
}
|
}
|
||||||
+1
@@ -133,6 +133,7 @@ public object ExpectedCompletionUtils {
|
|||||||
NOTHING_ELSE_PREFIX,
|
NOTHING_ELSE_PREFIX,
|
||||||
RUNTIME_TYPE,
|
RUNTIME_TYPE,
|
||||||
COMPLETION_TYPE_PREFIX,
|
COMPLETION_TYPE_PREFIX,
|
||||||
|
LightClassComputationControl.LIGHT_CLASS_DIRECTIVE,
|
||||||
AstAccessControl.ALLOW_AST_ACCESS_DIRECTIVE)
|
AstAccessControl.ALLOW_AST_ACCESS_DIRECTIVE)
|
||||||
|
|
||||||
public fun itemsShouldExist(fileText: String, platform: TargetPlatform?): Array<CompletionProposal> {
|
public fun itemsShouldExist(fileText: String, platform: TargetPlatform?): Array<CompletionProposal> {
|
||||||
|
|||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* 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.completion.test
|
||||||
|
|
||||||
|
import com.intellij.openapi.components.ComponentManager
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.impl.java.stubs.PsiClassStub
|
||||||
|
import com.intellij.psi.impl.java.stubs.PsiJavaFileStub
|
||||||
|
import org.jetbrains.kotlin.asJava.StubComputationTracker
|
||||||
|
import org.jetbrains.kotlin.test.InTextDirectivesUtils
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.picocontainer.MutablePicoContainer
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
object LightClassComputationControl {
|
||||||
|
fun testWithControl(project: Project, testText: String, testBody: () -> Unit) {
|
||||||
|
val expectedLightClassFqNames = InTextDirectivesUtils.findLinesWithPrefixesRemoved(
|
||||||
|
testText, "// $LIGHT_CLASS_DIRECTIVE"
|
||||||
|
).map { it.trim() }
|
||||||
|
|
||||||
|
val actualFqNames = ArrayList<String>()
|
||||||
|
val stubComputationTracker = object : StubComputationTracker {
|
||||||
|
override fun onStubComputed(javaFileStub: PsiJavaFileStub) {
|
||||||
|
val qualifiedName = (javaFileStub.childrenStubs.single() as PsiClassStub<*>).qualifiedName!!
|
||||||
|
actualFqNames.add(qualifiedName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.withServiceRegistered<StubComputationTracker>(stubComputationTracker) {
|
||||||
|
testBody()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expectedLightClassFqNames.toSortedSet() != actualFqNames.toSortedSet()) {
|
||||||
|
Assert.fail(
|
||||||
|
"Expected to compute: ${expectedLightClassFqNames.prettyToString()}\n" +
|
||||||
|
"Actually computed: ${actualFqNames.prettyToString()}\n" +
|
||||||
|
"Use $LIGHT_CLASS_DIRECTIVE to specify expected light class computations"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val LIGHT_CLASS_DIRECTIVE = "LIGHT_CLASS:"
|
||||||
|
|
||||||
|
private fun List<String>.prettyToString() = if (isEmpty()) "<empty>" else joinToString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T : Any> ComponentManager.withServiceRegistered(instance: T, body: () -> Unit) {
|
||||||
|
val picoContainer = picoContainer as MutablePicoContainer
|
||||||
|
val key = T::class.java.name
|
||||||
|
try {
|
||||||
|
picoContainer.unregisterComponent(key)
|
||||||
|
picoContainer.registerComponentInstance(key, instance)
|
||||||
|
body()
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
picoContainer.unregisterComponent(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user