add ultra-light classes/members that work without backend in simple cases

This commit is contained in:
peter
2018-10-25 17:58:05 +02:00
parent 387efc3791
commit ebc998d710
48 changed files with 2502 additions and 98 deletions
@@ -16,23 +16,171 @@
package org.jetbrains.kotlin.idea.caches.resolve
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.PsiElement
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.CachedValueProvider
import com.intellij.psi.util.CachedValuesManager
import com.intellij.psi.util.PsiModificationTracker
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.util.containers.ConcurrentFactoryMap
import org.jetbrains.kotlin.asJava.LightClassBuilder
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.builder.InvalidLightClassDataHolder
import org.jetbrains.kotlin.asJava.builder.LightClassDataHolder
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
import org.jetbrains.kotlin.asJava.classes.UltraLightSupport
import org.jetbrains.kotlin.asJava.classes.shouldNotBeVisibleAsLightClass
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.idea.caches.lightClasses.IDELightClassContexts
import org.jetbrains.kotlin.idea.caches.lightClasses.LazyLightClassDataHolder
import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.jetbrains.kotlin.idea.resolve.frontendService
import org.jetbrains.kotlin.idea.stubindex.KotlinTypeAliasShortNameIndex
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.NoDescriptorForDeclarationException
import java.util.concurrent.ConcurrentMap
class IDELightClassGenerationSupport(private val project: Project) : LightClassGenerationSupport() {
override fun createUltraLightClass(element: KtClassOrObject): KtUltraLightClass? {
if (element.shouldNotBeVisibleAsLightClass() ||
element is KtObjectDeclaration && element.isObjectLiteral() ||
element.isLocal ||
element is KtEnumEntry
) {
return null
}
val module = ModuleUtilCore.findModuleForPsiElement(element) ?: return null
return KtUltraLightClass(element, object : UltraLightSupport {
override fun isTooComplexForUltraLightGeneration(element: KtClassOrObject): Boolean {
val facet = KotlinFacet.get(module)
val pluginClasspath = facet?.configuration?.settings?.compilerArguments?.pluginClasspaths
if (!pluginClasspath.isNullOrEmpty()) {
LOG.debug { "Using heavy light classes for ${element.fqName?.asString()} because of compiler plugins $pluginClasspath" }
return true
}
val problem = findTooComplexDeclaration(element)
if (problem != null) {
LOG.debug {
"Using heavy light classes for ${element.fqName?.asString()} because of ${StringUtil.trimLog(problem.text, 100)}"
}
return true
}
return false
}
override val moduleName: String = module.name
override fun findAnnotation(owner: KtAnnotated, fqName: FqName): Pair<KtAnnotationEntry, AnnotationDescriptor>? {
val candidates = owner.annotationEntries.filter { it.shortName == fqName.shortName() || hasAlias(owner, fqName.shortName()) }
for (entry in candidates) {
val descriptor = analyze(entry).get(BindingContext.ANNOTATION, entry)
if (descriptor?.fqName == fqName) {
return Pair(entry, descriptor)
}
}
return null
}
})
}
private fun findTooComplexDeclaration(declaration: KtDeclaration): PsiElement? {
fun KtAnnotationEntry.seemsNonTrivial(): Boolean {
val name = shortName
return name == null || hasAlias(declaration, name) || name.asString().startsWith("Jvm") && name.asString() != "JvmStatic"
}
if (declaration.hasExpectModifier() ||
declaration.hasModifier(KtTokens.ANNOTATION_KEYWORD) ||
declaration.hasModifier(KtTokens.INLINE_KEYWORD) && declaration is KtClassOrObject ||
declaration.hasModifier(KtTokens.DATA_KEYWORD) ||
declaration.hasModifier(KtTokens.ENUM_KEYWORD) ||
declaration.hasModifier(KtTokens.SUSPEND_KEYWORD)) {
return declaration
}
declaration.annotationEntries.find(KtAnnotationEntry::seemsNonTrivial)?.let { return it }
if (declaration is KtClassOrObject) {
declaration.superTypeListEntries.find { it is KtDelegatedSuperTypeEntry }?.let { return it }
declaration.primaryConstructor?.let { findTooComplexDeclaration(it) }?.let { return it }
for (d in declaration.declarations) {
if (d is KtClassOrObject && !(d is KtObjectDeclaration && d.isCompanion())) continue
findTooComplexDeclaration(d)?.let { return it }
}
if (implementsKotlinCollection(declaration)) {
return declaration.getSuperTypeList()
}
}
if (declaration is KtCallableDeclaration) {
declaration.valueParameters.mapNotNull { findTooComplexDeclaration(it) }.firstOrNull()?.let { return it }
if (declaration.typeReference == null && (declaration as? KtFunction)?.hasBlockBody() != true) {
findPotentiallyReturnedAnonymousObject(declaration)?.let { return it }
}
if (declaration.typeReference?.hasModifier(KtTokens.SUSPEND_KEYWORD) == true) {
return declaration.typeReference
}
}
if (declaration is KtProperty) {
declaration.accessors.mapNotNull { findTooComplexDeclaration(it) }.firstOrNull()?.let { return it }
}
return null
}
private fun findPotentiallyReturnedAnonymousObject(declaration: KtDeclaration): KtObjectDeclaration? {
val spine = declaration.containingKtFile.stubbedSpine
for (i in 0 until spine.stubCount) {
if (spine.getStubType(i) == KtStubElementTypes.OBJECT_DECLARATION) {
val obj = spine.getStubPsi(i) as KtObjectDeclaration
if (obj.isObjectLiteral() && PsiTreeUtil.isContextAncestor(declaration, obj, true)) {
return obj
}
}
}
return null
}
private fun implementsKotlinCollection(classOrObject: KtClassOrObject): Boolean {
if (classOrObject.superTypeListEntries.isEmpty()) return false
return (resolveToDescriptor(classOrObject) as? ClassifierDescriptor)?.getAllSuperClassifiers()?.any {
it.fqNameSafe.asString().startsWith("kotlin.collections.")
} == true
}
private fun hasAlias(element: KtElement, shortName: Name): Boolean = allAliases(element.containingKtFile)[shortName.asString()] == true
private fun allAliases(file: KtFile): ConcurrentMap<String, Boolean> = CachedValuesManager.getCachedValue(file) {
val importAliases = file.importDirectives.mapNotNull { it.aliasName }.toSet()
val map = ConcurrentFactoryMap.createMap<String, Boolean> { s ->
s in importAliases || KotlinTypeAliasShortNameIndex.getInstance().get(s, project, file.resolveScope).isNotEmpty()
}
CachedValueProvider.Result.create<ConcurrentMap<String, Boolean>>(map, PsiModificationTracker.MODIFICATION_COUNT)
}
class IDELightClassGenerationSupport(project: Project) : LightClassGenerationSupport() {
private val scopeFileComparator = JavaElementFinder.byClasspathComparator(GlobalSearchScope.allScope(project))
override fun createDataHolderForClass(classOrObject: KtClassOrObject, builder: LightClassBuilder): LightClassDataHolder.ForClass {
@@ -0,0 +1,125 @@
/*
* Copyright 2010-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.perf
import com.intellij.psi.*
import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.asJava.LightClassGenerationSupport
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.classes.KtUltraLightClass
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtFile
import org.junit.Assert
@TestOnly
object UltraLightChecker {
fun checkClassEquivalence(file: KtFile) {
for (ktClass in allClasses(file)) {
checkClassEquivalence(ktClass)
}
}
fun allClasses(file: KtFile): List<KtClassOrObject> =
SyntaxTraverser.psiTraverser(file).filter(KtClassOrObject::class.java).toList()
fun checkClassEquivalence(ktClass: KtClassOrObject): KtUltraLightClass? {
val gold = KtLightClassForSourceDeclaration.create(ktClass)
val ultraLightClass = LightClassGenerationSupport.getInstance(ktClass.project).createUltraLightClass(ktClass) ?: return null
if (gold != null) {
Assert.assertFalse(gold.javaClass.name.contains("Ultra"))
}
val goldText = gold?.renderClass().orEmpty()
val ultraText = ultraLightClass.renderClass()
if (goldText != ultraText) {
Assert.assertEquals(
"// Classic implementation:\n$goldText",
"// Ultra-light implementation:\n$ultraText"
)
}
return ultraLightClass
}
private fun PsiAnnotation.renderAnnotation() =
"@" + qualifiedName + "(" + parameterList.attributes.joinToString { it.name + "=" + (it.value?.text ?: "?") } + ")"
private fun PsiModifierListOwner.renderModifiers(): String {
val buffer = StringBuilder()
for (annotation in annotations) {
buffer.append(annotation.renderAnnotation())
buffer.append(if (this is PsiParameter) " " else "\n")
}
for (modifier in PsiModifier.MODIFIERS.filter(::hasModifierProperty)) {
buffer.append(modifier).append(" ")
}
return buffer.toString()
}
private fun PsiType.renderType() = getCanonicalText(true)
private fun PsiReferenceList?.renderRefList(keyword: String): String {
if (this == null || this.referencedTypes.isEmpty()) return ""
return " " + keyword + " " + referencedTypes.joinToString { it.renderType() }
}
private fun PsiVariable.renderVar(): String {
var result = this.renderModifiers() + type.renderType() + " " + name
if (this is PsiParameter && this.isVarArgs) {
result += " /* vararg */"
}
computeConstantValue()?.let { result += " /* constant value $it */" }
return result
}
private fun PsiTypeParameterListOwner.renderTypeParams() =
if (typeParameters.isEmpty()) ""
else "<" + typeParameters.joinToString {
val bounds =
if (it.extendsListTypes.isNotEmpty())
" extends " + it.extendsListTypes.joinToString(" & ", transform = { it.renderType() })
else ""
it.name!! + bounds
} + "> "
private fun PsiMethod.renderMethod() =
renderModifiers() +
(if (isVarArgs) "/* vararg */ " else "") +
renderTypeParams() +
(returnType?.renderType() ?: "") + " " +
name +
"(" + parameterList.parameters.joinToString { it.renderModifiers() + it.type.renderType() } + ")" +
(this as? PsiAnnotationMethod)?.defaultValue?.let { " default " + it.text }.orEmpty() +
throwsList.referencedTypes.let { thrownTypes ->
if (thrownTypes.isEmpty()) ""
else " throws " + thrownTypes.joinToString { it.renderType() }
} +
";"
private fun PsiClass.renderClass(): String {
val classWord = when {
isAnnotationType -> "@interface"
isInterface -> "interface"
isEnum -> "enum"
else -> "class"
}
return renderModifiers() +
classWord + " " +
name + " /* " + qualifiedName + "*/" +
renderTypeParams() +
extendsList.renderRefList("extends") +
implementsList.renderRefList("implements") +
" {\n" +
(if (isEnum) fields.filterIsInstance<PsiEnumConstant>().joinToString(",\n") { it.name } + ";\n\n" else "") +
fields.filterNot { it is PsiEnumConstant }.map { it.renderVar().prependIndent(" ") + ";\n\n" }.sorted().joinToString("") +
methods.map { it.renderMethod().prependIndent(" ") + "\n\n" }.sorted().joinToString("") +
innerClasses.map { "class ${it.name} ...\n\n".prependIndent(" ") }.sorted().joinToString("") +
"}"
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2010-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.perf
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
import org.jetbrains.kotlin.idea.refactoring.toPsiFile
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtVisitorVoid
import java.util.*
import kotlin.system.measureNanoTime
class WholeProjectLightClassTest : WholeProjectPerformanceTest(), WholeProjectKotlinFileProvider {
override fun doTest(file: VirtualFile): PerFileTestResult {
val results = mutableMapOf<String, Long>()
var totalNs = 0L
val psiFile = file.toPsiFile(project) ?: run {
return WholeProjectPerformanceTest.PerFileTestResult(results, totalNs, listOf(AssertionError("PsiFile not found for $file")))
}
val errors = mutableListOf<Throwable>()
fun buildAllLightClasses(name: String, predicate: (KtClassOrObject) -> Boolean) {
val result = measureNanoTime {
try {
// Build light class by PsiFile
psiFile.acceptRecursively(object : KtVisitorVoid() {
override fun visitClassOrObject(classOrObject: KtClassOrObject) {
if (!predicate(classOrObject)) return
val lightClass = classOrObject.toLightClass() as? KtLightClassForSourceDeclaration ?: return
Arrays.hashCode(lightClass.superTypes)
Arrays.hashCode(lightClass.fields)
Arrays.hashCode(lightClass.methods)
// Just to be sure: access types
lightClass.fields.map { it.type }.hashCode()
lightClass.methods.map { it.returnType }.hashCode()
lightClass.hashCode()
}
})
} catch (t: Throwable) {
t.printStackTrace()
errors += t
}
}
results[name] = result
totalNs += result
}
buildAllLightClasses("LightClasses_Top") {
it.containingDeclarationForPseudocode == null
}
buildAllLightClasses("LightClasses_Members") {
!it.isLocal && it.containingDeclarationForPseudocode is KtClassOrObject
}
return PerFileTestResult(results, totalNs, errors)
}
fun testUltraLightPerformance() {
Registry.get("kotlin.use.ultra.light.classes").setValue(true, testRootDisposable)
testWholeProjectPerformance()
}
}
@@ -0,0 +1,33 @@
/*
* Copyright 2010-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.perf
import com.intellij.openapi.vfs.VirtualFile
import org.jetbrains.kotlin.idea.refactoring.toPsiFile
import org.jetbrains.kotlin.psi.KtFile
import kotlin.system.measureNanoTime
// abstract so that it doesn't run in CI until known issues (JDK absence in the test project, different module names in mangled methods) are addressed
abstract class WholeProjectUltraLightClassTest : WholeProjectPerformanceTest(), WholeProjectKotlinFileProvider {
override fun doTest(file: VirtualFile): PerFileTestResult {
val psiFile = file.toPsiFile(project) as? KtFile ?: run {
return WholeProjectPerformanceTest.PerFileTestResult(mapOf(), 0, listOf(AssertionError("PsiFile not found for $file")))
}
val errors = mutableListOf<Throwable>()
val elapsed = measureNanoTime {
try {
UltraLightChecker.checkClassEquivalence(psiFile)
} catch (t: Throwable) {
t.printStackTrace()
errors += t
}
}
return PerFileTestResult(mapOf("ultraLightEquivalence" to elapsed), elapsed, errors)
}
}
+5
View File
@@ -170,5 +170,10 @@
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JvmIdePlatformKindTooling"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JsIdePlatformKindTooling"/>
<registryKey key="kotlin.use.ultra.light.classes"
description="Whether to use an experimental implementation of Kotlin-as-Java classes"
defaultValue="false"
restartRequired="false"/>
</extensions>
</idea-plugin>
@@ -0,0 +1,33 @@
/*
* Copyright 2010-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.asJava.classes
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.idea.perf.UltraLightChecker
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.psi.KtFile
import java.io.File
abstract class AbstractUltraLightClassLoadingTest : KotlinLightCodeInsightFixtureTestCase() {
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
fun doTest(testDataPath: String) {
val file = myFixture.addFileToProject(testDataPath, File(testDataPath).readText()) as KtFile
for (ktClass in UltraLightChecker.allClasses(file)) {
val clsLoadingExpected = ktClass.docComment?.text?.contains("should load cls") == true
val ultraLightClass = UltraLightChecker.checkClassEquivalence(ktClass)
if (ultraLightClass != null) {
assertEquals(
"Cls-loaded status differs from expected for ${ultraLightClass.qualifiedName}",
clsLoadingExpected,
ultraLightClass.isClsDelegateLoaded
)
}
}
}
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-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.asJava.classes
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.idea.perf.UltraLightChecker
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.psi.KtFile
import java.io.File
abstract class AbstractUltraLightClassSanityTest : KotlinLightCodeInsightFixtureTestCase() {
override fun getProjectDescriptor(): LightProjectDescriptor = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
fun doTest(testDataPath: String) {
val ioFile = File(testDataPath)
if (ioFile.name == "AllOpenAnnotatedClasses.kt") {
return //tests allopen compiler plugin that we don't have in this test
}
val file = myFixture.addFileToProject(testDataPath, ioFile.readText()) as KtFile
UltraLightChecker.checkClassEquivalence(file)
}
}
@@ -0,0 +1,131 @@
/*
* Copyright 2010-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.asJava.classes;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/asJava/ultraLightClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class UltraLightClassLoadingTestGenerated extends AbstractUltraLightClassLoadingTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInUltraLightClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/ultraLightClasses"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("annotations.kt")
public void testAnnotations() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/annotations.kt");
}
@TestMetadata("classModifiers.kt")
public void testClassModifiers() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/classModifiers.kt");
}
@TestMetadata("constructors.kt")
public void testConstructors() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/constructors.kt");
}
@TestMetadata("coroutines.kt")
public void testCoroutines() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/coroutines.kt");
}
@TestMetadata("dataClasses.kt")
public void testDataClasses() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/dataClasses.kt");
}
@TestMetadata("delegatingToInterfaces.kt")
public void testDelegatingToInterfaces() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/delegatingToInterfaces.kt");
}
@TestMetadata("enums.kt")
public void testEnums() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/enums.kt");
}
@TestMetadata("generics.kt")
public void testGenerics() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/generics.kt");
}
@TestMetadata("implementingKotlinCollections.kt")
public void testImplementingKotlinCollections() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/implementingKotlinCollections.kt");
}
@TestMetadata("importAliases.kt")
public void testImportAliases() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/importAliases.kt");
}
@TestMetadata("inferringAnonymousObjectTypes.kt")
public void testInferringAnonymousObjectTypes() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/inferringAnonymousObjectTypes.kt");
}
@TestMetadata("inheritance.kt")
public void testInheritance() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/inheritance.kt");
}
@TestMetadata("inlineClasses.kt")
public void testInlineClasses() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/inlineClasses.kt");
}
@TestMetadata("jvmName.kt")
public void testJvmName() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/jvmName.kt");
}
@TestMetadata("jvmOverloads.kt")
public void testJvmOverloads() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/jvmOverloads.kt");
}
@TestMetadata("objects.kt")
public void testObjects() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/objects.kt");
}
@TestMetadata("properties.kt")
public void testProperties() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/properties.kt");
}
@TestMetadata("simpleFunctions.kt")
public void testSimpleFunctions() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/simpleFunctions.kt");
}
@TestMetadata("throwsAnnotation.kt")
public void testThrowsAnnotation() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/throwsAnnotation.kt");
}
@TestMetadata("typeAliases.kt")
public void testTypeAliases() throws Exception {
runTest("compiler/testData/asJava/ultraLightClasses/typeAliases.kt");
}
}
@@ -0,0 +1,548 @@
/*
* Copyright 2010-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.asJava.classes;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/asJava/lightClasses")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class UltraLightClassSanityTestGenerated extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInLightClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("AnnotationClass.kt")
public void testAnnotationClass() throws Exception {
runTest("compiler/testData/asJava/lightClasses/AnnotationClass.kt");
}
@TestMetadata("DataClassWithCustomImplementedMembers.kt")
public void testDataClassWithCustomImplementedMembers() throws Exception {
runTest("compiler/testData/asJava/lightClasses/DataClassWithCustomImplementedMembers.kt");
}
@TestMetadata("DelegatedNested.kt")
public void testDelegatedNested() throws Exception {
runTest("compiler/testData/asJava/lightClasses/DelegatedNested.kt");
}
@TestMetadata("Delegation.kt")
public void testDelegation() throws Exception {
runTest("compiler/testData/asJava/lightClasses/Delegation.kt");
}
@TestMetadata("DeprecatedEnumEntry.kt")
public void testDeprecatedEnumEntry() throws Exception {
runTest("compiler/testData/asJava/lightClasses/DeprecatedEnumEntry.kt");
}
@TestMetadata("DeprecatedNotHiddenInClass.kt")
public void testDeprecatedNotHiddenInClass() throws Exception {
runTest("compiler/testData/asJava/lightClasses/DeprecatedNotHiddenInClass.kt");
}
@TestMetadata("DollarsInName.kt")
public void testDollarsInName() throws Exception {
runTest("compiler/testData/asJava/lightClasses/DollarsInName.kt");
}
@TestMetadata("DollarsInNameNoPackage.kt")
public void testDollarsInNameNoPackage() throws Exception {
runTest("compiler/testData/asJava/lightClasses/DollarsInNameNoPackage.kt");
}
@TestMetadata("ExtendingInterfaceWithDefaultImpls.kt")
public void testExtendingInterfaceWithDefaultImpls() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ExtendingInterfaceWithDefaultImpls.kt");
}
@TestMetadata("HiddenDeprecated.kt")
public void testHiddenDeprecated() throws Exception {
runTest("compiler/testData/asJava/lightClasses/HiddenDeprecated.kt");
}
@TestMetadata("HiddenDeprecatedInClass.kt")
public void testHiddenDeprecatedInClass() throws Exception {
runTest("compiler/testData/asJava/lightClasses/HiddenDeprecatedInClass.kt");
}
@TestMetadata("InheritingInterfaceDefaultImpls.kt")
public void testInheritingInterfaceDefaultImpls() throws Exception {
runTest("compiler/testData/asJava/lightClasses/InheritingInterfaceDefaultImpls.kt");
}
@TestMetadata("JvmNameOnMember.kt")
public void testJvmNameOnMember() throws Exception {
runTest("compiler/testData/asJava/lightClasses/JvmNameOnMember.kt");
}
@TestMetadata("JvmStatic.kt")
public void testJvmStatic() throws Exception {
runTest("compiler/testData/asJava/lightClasses/JvmStatic.kt");
}
@TestMetadata("NestedObjects.kt")
public void testNestedObjects() throws Exception {
runTest("compiler/testData/asJava/lightClasses/NestedObjects.kt");
}
@TestMetadata("NonDataClassWithComponentFunctions.kt")
public void testNonDataClassWithComponentFunctions() throws Exception {
runTest("compiler/testData/asJava/lightClasses/NonDataClassWithComponentFunctions.kt");
}
@TestMetadata("PublishedApi.kt")
public void testPublishedApi() throws Exception {
runTest("compiler/testData/asJava/lightClasses/PublishedApi.kt");
}
@TestMetadata("SpecialAnnotationsOnAnnotationClass.kt")
public void testSpecialAnnotationsOnAnnotationClass() throws Exception {
runTest("compiler/testData/asJava/lightClasses/SpecialAnnotationsOnAnnotationClass.kt");
}
@TestMetadata("StubOrderForOverloads.kt")
public void testStubOrderForOverloads() throws Exception {
runTest("compiler/testData/asJava/lightClasses/StubOrderForOverloads.kt");
}
@TestMetadata("VarArgs.kt")
public void testVarArgs() throws Exception {
runTest("compiler/testData/asJava/lightClasses/VarArgs.kt");
}
@TestMetadata("compiler/testData/asJava/lightClasses/compilationErrors")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class CompilationErrors extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
@TestMetadata("ActualClass.kt")
public void testActualClass() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ActualClass.kt");
}
@TestMetadata("ActualTypeAlias.kt")
public void testActualTypeAlias() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ActualTypeAlias.kt");
}
@TestMetadata("ActualTypeAliasCustomJvmPackageName.kt")
public void testActualTypeAliasCustomJvmPackageName() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ActualTypeAliasCustomJvmPackageName.kt");
}
public void testAllFilesPresentInCompilationErrors() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/compilationErrors"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("AllInlineOnly.kt")
public void testAllInlineOnly() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/AllInlineOnly.kt");
}
@TestMetadata("AnnotationModifiers.kt")
public void testAnnotationModifiers() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/AnnotationModifiers.kt");
}
@TestMetadata("ExpectClass.kt")
public void testExpectClass() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ExpectClass.kt");
}
@TestMetadata("ExpectObject.kt")
public void testExpectObject() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ExpectObject.kt");
}
@TestMetadata("ExpectedNestedClass.kt")
public void testExpectedNestedClass() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ExpectedNestedClass.kt");
}
@TestMetadata("ExpectedNestedClassInObject.kt")
public void testExpectedNestedClassInObject() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/ExpectedNestedClassInObject.kt");
}
@TestMetadata("JvmPackageName.kt")
public void testJvmPackageName() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/JvmPackageName.kt");
}
@TestMetadata("LocalInAnnotation.kt")
public void testLocalInAnnotation() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/LocalInAnnotation.kt");
}
@TestMetadata("PrivateInTrait.kt")
public void testPrivateInTrait() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/PrivateInTrait.kt");
}
@TestMetadata("RepetableAnnotations.kt")
public void testRepetableAnnotations() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/RepetableAnnotations.kt");
}
@TestMetadata("SameName.kt")
public void testSameName() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/SameName.kt");
}
@TestMetadata("TopLevelDestructuring.kt")
public void testTopLevelDestructuring() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/TopLevelDestructuring.kt");
}
@TestMetadata("TraitClassObjectField.kt")
public void testTraitClassObjectField() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/TraitClassObjectField.kt");
}
@TestMetadata("WrongAnnotations.kt")
public void testWrongAnnotations() throws Exception {
runTest("compiler/testData/asJava/lightClasses/compilationErrors/WrongAnnotations.kt");
}
}
@TestMetadata("compiler/testData/asJava/lightClasses/delegation")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Delegation extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInDelegation() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/delegation"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("Function.kt")
public void testFunction() throws Exception {
runTest("compiler/testData/asJava/lightClasses/delegation/Function.kt");
}
@TestMetadata("Property.kt")
public void testProperty() throws Exception {
runTest("compiler/testData/asJava/lightClasses/delegation/Property.kt");
}
@TestMetadata("WithPlatformTypes.NoCompile.kt")
public void testWithPlatformTypes_NoCompile() throws Exception {
runTest("compiler/testData/asJava/lightClasses/delegation/WithPlatformTypes.NoCompile.kt");
}
}
@TestMetadata("compiler/testData/asJava/lightClasses/facades")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Facades extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInFacades() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/facades"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("AllPrivate.kt")
public void testAllPrivate() throws Exception {
runTest("compiler/testData/asJava/lightClasses/facades/AllPrivate.kt");
}
@TestMetadata("EmptyFile.NoCompile.kt")
public void testEmptyFile_NoCompile() throws Exception {
runTest("compiler/testData/asJava/lightClasses/facades/EmptyFile.NoCompile.kt");
}
@TestMetadata("MultiFile.kt")
public void testMultiFile() throws Exception {
runTest("compiler/testData/asJava/lightClasses/facades/MultiFile.kt");
}
@TestMetadata("SingleFile.kt")
public void testSingleFile() throws Exception {
runTest("compiler/testData/asJava/lightClasses/facades/SingleFile.kt");
}
@TestMetadata("SingleJvmClassName.kt")
public void testSingleJvmClassName() throws Exception {
runTest("compiler/testData/asJava/lightClasses/facades/SingleJvmClassName.kt");
}
}
@TestMetadata("compiler/testData/asJava/lightClasses/ideRegression")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class IdeRegression extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInIdeRegression() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/ideRegression"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("AllOpenAnnotatedClasses.kt")
public void testAllOpenAnnotatedClasses() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/AllOpenAnnotatedClasses.kt");
}
@TestMetadata("ImplementingCharSequenceAndNumber.kt")
public void testImplementingCharSequenceAndNumber() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/ImplementingCharSequenceAndNumber.kt");
}
@TestMetadata("ImplementingMap.kt")
public void testImplementingMap() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMap.kt");
}
@TestMetadata("ImplementingMutableSet.kt")
public void testImplementingMutableSet() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/ImplementingMutableSet.kt");
}
@TestMetadata("InheritingInterfaceDefaultImpls.kt")
public void testInheritingInterfaceDefaultImpls() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/InheritingInterfaceDefaultImpls.kt");
}
@TestMetadata("OverridingFinalInternal.kt")
public void testOverridingFinalInternal() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingFinalInternal.kt");
}
@TestMetadata("OverridingFinalInternal.extra.kt")
public void testOverridingFinalInternal_extra() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingFinalInternal.extra.kt");
}
@TestMetadata("OverridingInternal.kt")
public void testOverridingInternal() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.kt");
}
@TestMetadata("OverridingInternal.extra.kt")
public void testOverridingInternal_extra() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingInternal.extra.kt");
}
@TestMetadata("OverridingProtected.kt")
public void testOverridingProtected() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingProtected.kt");
}
@TestMetadata("OverridingProtected.extra.kt")
public void testOverridingProtected_extra() throws Exception {
runTest("compiler/testData/asJava/lightClasses/ideRegression/OverridingProtected.extra.kt");
}
}
@TestMetadata("compiler/testData/asJava/lightClasses/local")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Local extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInLocal() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/local"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("DollarsInNameLocal.kt")
public void testDollarsInNameLocal() throws Exception {
runTest("compiler/testData/asJava/lightClasses/local/DollarsInNameLocal.kt");
}
}
@TestMetadata("compiler/testData/asJava/lightClasses/nullabilityAnnotations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NullabilityAnnotations extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInNullabilityAnnotations() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/nullabilityAnnotations"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("Class.kt")
public void testClass() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Class.kt");
}
@TestMetadata("ClassObjectField.kt")
public void testClassObjectField() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassObjectField.kt");
}
@TestMetadata("ClassWithConstructor.kt")
public void testClassWithConstructor() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructor.kt");
}
@TestMetadata("ClassWithConstructorAndProperties.kt")
public void testClassWithConstructorAndProperties() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/ClassWithConstructorAndProperties.kt");
}
@TestMetadata("FileFacade.kt")
public void testFileFacade() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/FileFacade.kt");
}
@TestMetadata("Generic.kt")
public void testGeneric() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Generic.kt");
}
@TestMetadata("IntOverridesAny.kt")
public void testIntOverridesAny() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/IntOverridesAny.kt");
}
@TestMetadata("JvmOverloads.kt")
public void testJvmOverloads() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/JvmOverloads.kt");
}
@TestMetadata("NullableUnitReturn.kt")
public void testNullableUnitReturn() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/NullableUnitReturn.kt");
}
@TestMetadata("OverrideAnyWithUnit.kt")
public void testOverrideAnyWithUnit() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/OverrideAnyWithUnit.kt");
}
@TestMetadata("PlatformTypes.kt")
public void testPlatformTypes() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/PlatformTypes.kt");
}
@TestMetadata("Primitives.kt")
public void testPrimitives() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Primitives.kt");
}
@TestMetadata("PrivateInClass.kt")
public void testPrivateInClass() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/PrivateInClass.kt");
}
@TestMetadata("Synthetic.kt")
public void testSynthetic() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Synthetic.kt");
}
@TestMetadata("Trait.kt")
public void testTrait() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/Trait.kt");
}
@TestMetadata("UnitAsGenericArgument.kt")
public void testUnitAsGenericArgument() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitAsGenericArgument.kt");
}
@TestMetadata("UnitParameter.kt")
public void testUnitParameter() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/UnitParameter.kt");
}
@TestMetadata("VoidReturn.kt")
public void testVoidReturn() throws Exception {
runTest("compiler/testData/asJava/lightClasses/nullabilityAnnotations/VoidReturn.kt");
}
}
@TestMetadata("compiler/testData/asJava/lightClasses/object")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Object extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInObject() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/object"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("SimpleObject.kt")
public void testSimpleObject() throws Exception {
runTest("compiler/testData/asJava/lightClasses/object/SimpleObject.kt");
}
}
@TestMetadata("compiler/testData/asJava/lightClasses/publicField")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PublicField extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInPublicField() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/publicField"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("CompanionObject.kt")
public void testCompanionObject() throws Exception {
runTest("compiler/testData/asJava/lightClasses/publicField/CompanionObject.kt");
}
@TestMetadata("Simple.kt")
public void testSimple() throws Exception {
runTest("compiler/testData/asJava/lightClasses/publicField/Simple.kt");
}
}
@TestMetadata("compiler/testData/asJava/lightClasses/script")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Script extends AbstractUltraLightClassSanityTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
public void testAllFilesPresentInScript() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/asJava/lightClasses/script"), Pattern.compile("^(.+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("HelloWorld.kts")
public void testHelloWorld() throws Exception {
runTest("compiler/testData/asJava/lightClasses/script/HelloWorld.kts");
}
@TestMetadata("InnerClasses.kts")
public void testInnerClasses() throws Exception {
runTest("compiler/testData/asJava/lightClasses/script/InnerClasses.kts");
}
}
}