Return Kotlin fields and methods through KotlinShortNameCache
#KT-12205 Fixed
This commit is contained in:
committed by
Dmitry Jemerov
parent
b06bdcef75
commit
18feb8f622
@@ -16,14 +16,12 @@
|
||||
|
||||
package org.jetbrains.kotlin.asJava
|
||||
|
||||
import com.intellij.openapi.progress.ProcessCanceledException
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.java.stubs.PsiClassStub
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.stubs.PsiFileStub
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.util.SmartList
|
||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||
import org.jetbrains.kotlin.asJava.elements.*
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
@@ -31,6 +29,7 @@ import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.sequenceOfLazyValues
|
||||
|
||||
object LightClassUtil {
|
||||
|
||||
@@ -53,9 +52,11 @@ object LightClassUtil {
|
||||
|
||||
fun getLightClassAccessorMethods(accessor: KtPropertyAccessor): List<PsiMethod> {
|
||||
val property = accessor.getNonStrictParentOfType<KtProperty>() ?: return emptyList()
|
||||
val wrappers = getPsiMethodWrappers(property, true)
|
||||
return wrappers.filter { wrapper -> (accessor.isGetter && !JvmAbi.isSetterName(wrapper.name)) ||
|
||||
(accessor.isSetter && JvmAbi.isSetterName(wrapper.name)) }
|
||||
val wrappers = getPsiMethodWrappers(property)
|
||||
return wrappers.filter { wrapper ->
|
||||
(accessor.isGetter && !JvmAbi.isSetterName(wrapper.name)) ||
|
||||
(accessor.isSetter && JvmAbi.isSetterName(wrapper.name))
|
||||
}.toList()
|
||||
}
|
||||
|
||||
fun getLightFieldForCompanionObject(companionObject: KtClassOrObject): PsiField? {
|
||||
@@ -120,36 +121,16 @@ object LightClassUtil {
|
||||
}
|
||||
|
||||
fun getLightClassMethods(function: KtFunction): List<PsiMethod> {
|
||||
return getPsiMethodWrappers(function, true)
|
||||
return getPsiMethodWrappers(function).toList()
|
||||
}
|
||||
|
||||
private fun getPsiMethodWrapper(declaration: KtDeclaration): PsiMethod? {
|
||||
return getPsiMethodWrappers(declaration, false).firstOrNull()
|
||||
return getPsiMethodWrappers(declaration).firstOrNull()
|
||||
}
|
||||
|
||||
private fun getPsiMethodWrappers(declaration: KtDeclaration, collectAll: Boolean): List<PsiMethod> {
|
||||
val psiClass = getWrappingClass(declaration) ?: return emptyList()
|
||||
|
||||
val methods = SmartList<PsiMethod>()
|
||||
for (method in psiClass.methods.asList()) {
|
||||
try {
|
||||
if (method is KtLightMethod && method.kotlinOrigin === declaration) {
|
||||
methods.add(method)
|
||||
if (!collectAll) {
|
||||
return methods
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e: ProcessCanceledException) {
|
||||
throw e
|
||||
}
|
||||
catch (e: Throwable) {
|
||||
throw IllegalStateException(
|
||||
"Error while wrapping declaration " + declaration.name + "Context\n:" + method, e)
|
||||
}
|
||||
}
|
||||
|
||||
return methods
|
||||
private fun getPsiMethodWrappers(declaration: KtDeclaration): Sequence<PsiMethod> {
|
||||
return getWrappingClasses(declaration).flatMap { it.methods.asSequence() }
|
||||
.filter { method -> method is KtLightMethod && method.kotlinOrigin === declaration }
|
||||
}
|
||||
|
||||
private fun getWrappingClass(declaration: KtDeclaration): PsiClass? {
|
||||
@@ -185,6 +166,15 @@ object LightClassUtil {
|
||||
return null
|
||||
}
|
||||
|
||||
private fun getWrappingClasses(declaration: KtDeclaration): Sequence<PsiClass> {
|
||||
val wrapperClass = getWrappingClass(declaration) ?: return emptySequence()
|
||||
val wrapperClassOrigin = (wrapperClass as KtLightClass).kotlinOrigin
|
||||
if (wrapperClassOrigin is KtObjectDeclaration && wrapperClassOrigin.isCompanion()) {
|
||||
return sequenceOfLazyValues({ wrapperClass }, { wrapperClass.parent as PsiClass })
|
||||
}
|
||||
return sequenceOf(wrapperClass)
|
||||
}
|
||||
|
||||
fun canGenerateLightClass(declaration: KtDeclaration): Boolean {
|
||||
//noinspection unchecked
|
||||
return PsiTreeUtil.getParentOfType(declaration, KtFunction::class.java, KtProperty::class.java) == null
|
||||
@@ -197,7 +187,7 @@ object LightClassUtil {
|
||||
var setterWrapper = specialSetter
|
||||
val additionalAccessors = arrayListOf<PsiMethod>()
|
||||
|
||||
for (wrapper in getPsiMethodWrappers(ktDeclaration, true)) {
|
||||
for (wrapper in getPsiMethodWrappers(ktDeclaration)) {
|
||||
if (wrapper !is KtLightMethod) continue
|
||||
|
||||
if (wrapper.isSetter) {
|
||||
@@ -209,7 +199,7 @@ object LightClassUtil {
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (getterWrapper == null || getterWrapper == specialGetter) {
|
||||
if (getterWrapper == null || getterWrapper === specialGetter) {
|
||||
getterWrapper = wrapper
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import com.intellij.psi.impl.PsiVariableEx
|
||||
import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
@@ -31,4 +32,6 @@ interface KtLightElement<out T : KtElement, out D : PsiElement> : PsiNamedElemen
|
||||
|
||||
interface KtLightDeclaration<out T: KtDeclaration, out D: PsiElement>: KtLightElement<T, D>
|
||||
|
||||
interface KtLightField : PsiField, KtLightDeclaration<KtDeclaration, PsiField>, PsiVariableEx
|
||||
interface KtLightField : PsiField, KtLightDeclaration<KtDeclaration, PsiField>, PsiVariableEx {
|
||||
val lightMemberOrigin: LightMemberOrigin?
|
||||
}
|
||||
+22
-1
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.asJava.elements
|
||||
|
||||
import com.intellij.navigation.ItemPresentation
|
||||
import com.intellij.navigation.ItemPresentationProviders
|
||||
import com.intellij.navigation.NavigationItem
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.PsiVariableEx
|
||||
@@ -30,10 +33,11 @@ import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import java.lang.UnsupportedOperationException
|
||||
|
||||
// Copied from com.intellij.psi.impl.light.LightField
|
||||
sealed class KtLightFieldImpl(
|
||||
private val lightMemberOrigin: LightMemberOrigin?,
|
||||
override val lightMemberOrigin: LightMemberOrigin?,
|
||||
override val clsDelegate: PsiField,
|
||||
private val containingClass: KtLightClass
|
||||
) : LightElement(clsDelegate.manager, KotlinLanguage.INSTANCE), KtLightField {
|
||||
@@ -44,6 +48,8 @@ sealed class KtLightFieldImpl(
|
||||
|
||||
override fun getUseScope() = kotlinOrigin?.useScope ?: super.getUseScope()
|
||||
|
||||
override fun getPresentation(): ItemPresentation? = (kotlinOrigin ?: this).let { ItemPresentationProviders.getItemPresentation(it) }
|
||||
|
||||
override fun getName() = clsDelegate.name
|
||||
|
||||
override fun getNameIdentifier() = lightIdentifier
|
||||
@@ -92,6 +98,20 @@ sealed class KtLightFieldImpl(
|
||||
|
||||
override fun toString(): String = "${this.javaClass.simpleName}:$name"
|
||||
|
||||
override fun equals(other: Any?): Boolean =
|
||||
other is KtLightField &&
|
||||
name == other.name &&
|
||||
lightMemberOrigin == other.lightMemberOrigin &&
|
||||
containingClass == other.containingClass &&
|
||||
clsDelegate == other.clsDelegate
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = lightMemberOrigin?.hashCode() ?: 0
|
||||
result = 31 * result + clsDelegate.hashCode()
|
||||
result = 31 * result + containingClass.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
override val kotlinOrigin: KtDeclaration? get() = lightMemberOrigin?.originalElement
|
||||
|
||||
override fun getNavigationElement() = kotlinOrigin ?: super.getNavigationElement()
|
||||
@@ -111,6 +131,7 @@ sealed class KtLightFieldImpl(
|
||||
|
||||
override fun copy() = Factory.create(lightMemberOrigin?.copy(), clsDelegate, containingClass)
|
||||
|
||||
|
||||
class KtLightEnumConstant(
|
||||
origin: LightMemberOrigin?,
|
||||
override val clsDelegate: PsiEnumConstant,
|
||||
|
||||
@@ -182,4 +182,8 @@ fun accessorNameByPropertyName(name: String, accessor: KtLightMethod): String? {
|
||||
JvmAbi.isSetterName(methodName) -> JvmAbi.setterName(name)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
fun getAccessorNamesCandidatesByPropertyName(name: String): List<String> {
|
||||
return listOf(JvmAbi.setterName(name), JvmAbi.getterName(name))
|
||||
}
|
||||
@@ -25,14 +25,17 @@ import com.intellij.psi.search.PsiShortNamesCache
|
||||
import com.intellij.util.Processor
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import com.intellij.util.containers.HashSet
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.asJava.defaultImplsChild
|
||||
import org.jetbrains.kotlin.asJava.finder.JavaElementFinder
|
||||
import org.jetbrains.kotlin.asJava.getAccessorNamesCandidatesByPropertyName
|
||||
import org.jetbrains.kotlin.fileClasses.javaFileFacadeFqName
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinClassShortNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinFileFacadeShortNameIndex
|
||||
import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope
|
||||
import org.jetbrains.kotlin.idea.stubindex.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.java.getPropertyNamesCandidatesByAccessorName
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.sequenceOfLazyValues
|
||||
import java.util.*
|
||||
|
||||
class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache() {
|
||||
@@ -85,30 +88,79 @@ class KotlinShortNamesCache(private val project: Project) : PsiShortNamesCache()
|
||||
dest.addAll(allClassNames)
|
||||
}
|
||||
|
||||
override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array<PsiMethod>
|
||||
= emptyArray()
|
||||
override fun getMethodsByName(name: String, scope: GlobalSearchScope): Array<PsiMethod> {
|
||||
return getMethodSequenceByName(name, scope).toList().toTypedArray()
|
||||
}
|
||||
|
||||
override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array<PsiMethod>
|
||||
= emptyArray()
|
||||
fun getMethodSequenceByName(name: String, scope: GlobalSearchScope): Sequence<PsiMethod> {
|
||||
val propertiesIndex = KotlinPropertyShortNameIndex.getInstance()
|
||||
val functionIndex = KotlinFunctionShortNameIndex.getInstance()
|
||||
|
||||
override fun getFieldsByNameIfNotMoreThan(s: String, scope: GlobalSearchScope, i: Int): Array<PsiField>
|
||||
= emptyArray()
|
||||
val kotlinFunctionsPsi = functionIndex.get(name, project, scope).asSequence()
|
||||
.flatMap { LightClassUtil.getLightClassMethods(it).asSequence() }
|
||||
.filter { it.name == name }
|
||||
|
||||
val propertyAccessorsPsi = sequenceOfLazyValues({ getPropertyNamesCandidatesByAccessorName(Name.identifier(name)) })
|
||||
.flatMap { it.asSequence() }
|
||||
.flatMap { propertiesIndex.get(it.asString(), project, scope).asSequence() }
|
||||
.flatMap { LightClassUtil.getLightClassPropertyMethods(it).allDeclarations.asSequence() }
|
||||
.filter { it.name == name }
|
||||
.map { it as? PsiMethod }
|
||||
|
||||
return sequenceOfLazyValues({ kotlinFunctionsPsi }, { propertyAccessorsPsi }).flatMap { it }.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getMethodsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array<PsiMethod> {
|
||||
require(maxCount >= 0)
|
||||
val psiMethods = getMethodSequenceByName(name, scope)
|
||||
val limitedByMaxCount = psiMethods.take(maxCount).toList()
|
||||
if (limitedByMaxCount.size == 0)
|
||||
return PsiMethod.EMPTY_ARRAY
|
||||
return limitedByMaxCount.toTypedArray()
|
||||
}
|
||||
|
||||
override fun getFieldsByNameIfNotMoreThan(name: String, scope: GlobalSearchScope, maxCount: Int): Array<PsiField> {
|
||||
require(maxCount >= 0)
|
||||
val psiFields = getFieldSequenceByName(name, scope)
|
||||
val limitedByMaxCount = psiFields.take(maxCount).toList()
|
||||
if (limitedByMaxCount.size == 0)
|
||||
return PsiField.EMPTY_ARRAY
|
||||
return limitedByMaxCount.toTypedArray()
|
||||
}
|
||||
|
||||
override fun processMethodsWithName(name: String, scope: GlobalSearchScope, processor: Processor<PsiMethod>): Boolean
|
||||
= ContainerUtil.process(getMethodsByName(name, scope), processor)
|
||||
|
||||
override fun getAllMethodNames(): Array<String>
|
||||
= emptyArray()
|
||||
override fun getAllMethodNames(): Array<String> {
|
||||
val functionIndex = KotlinFunctionShortNameIndex.getInstance()
|
||||
val functionNames = functionIndex.getAllKeys(project)
|
||||
|
||||
val propertiesIndex = KotlinPropertyShortNameIndex.getInstance()
|
||||
val propertyAccessorNames = propertiesIndex.getAllKeys(project)
|
||||
.flatMap(::getAccessorNamesCandidatesByPropertyName)
|
||||
|
||||
return (functionNames + propertyAccessorNames).toTypedArray()
|
||||
}
|
||||
|
||||
override fun getAllMethodNames(set: HashSet<String>) {
|
||||
set.addAll(allMethodNames)
|
||||
}
|
||||
|
||||
override fun getFieldsByName(name: String, scope: GlobalSearchScope): Array<PsiField>
|
||||
= emptyArray()
|
||||
fun getFieldSequenceByName(name: String, scope: GlobalSearchScope): Sequence<PsiField> {
|
||||
return KotlinPropertyShortNameIndex.getInstance().get(name, project, scope).asSequence()
|
||||
.map { LightClassUtil.getLightClassBackingField(it) }
|
||||
.filterNotNull()
|
||||
}
|
||||
|
||||
override fun getAllFieldNames(): Array<String>
|
||||
= emptyArray()
|
||||
override fun getFieldsByName(name: String, scope: GlobalSearchScope): Array<PsiField> {
|
||||
return getFieldSequenceByName(name, scope).toList().toTypedArray()
|
||||
}
|
||||
|
||||
override fun getAllFieldNames(): Array<String> {
|
||||
return KotlinPropertyShortNameIndex.getInstance().getAllKeys(project).toTypedArray()
|
||||
}
|
||||
|
||||
override fun getAllFieldNames(set: HashSet<String>) {
|
||||
set.addAll(allFieldNames)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,18 +18,24 @@ package org.jetbrains.kotlin.idea.core
|
||||
|
||||
import com.intellij.codeInsight.JavaProjectCodeInsightSettings
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiFile
|
||||
import com.intellij.psi.PsiMember
|
||||
import com.intellij.psi.PsiModifier
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.PsiShortNamesCache
|
||||
import com.intellij.psi.stubs.StringStubIndexExtension
|
||||
import com.intellij.util.indexing.IdFilter
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightElement
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.*
|
||||
import org.jetbrains.kotlin.idea.core.extension.KotlinIndicesHelperExtension
|
||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInFileType
|
||||
import org.jetbrains.kotlin.idea.imports.importableFqName
|
||||
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
|
||||
import org.jetbrains.kotlin.idea.search.excludeKotlinSources
|
||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||
import org.jetbrains.kotlin.idea.stubindex.*
|
||||
import org.jetbrains.kotlin.idea.util.CallType
|
||||
@@ -59,6 +65,7 @@ class KotlinIndicesHelper(
|
||||
|
||||
private val moduleDescriptor = resolutionFacade.moduleDescriptor
|
||||
private val project = resolutionFacade.project
|
||||
private val scopeWithoutKotlin = scope.excludeKotlinSources() as GlobalSearchScope
|
||||
|
||||
private val descriptorFilter: (DeclarationDescriptor) -> Boolean = filter@ {
|
||||
if (it.isHiddenInResolution()) return@filter false
|
||||
@@ -202,9 +209,10 @@ class KotlinIndicesHelper(
|
||||
}
|
||||
|
||||
fun getJvmCallablesByName(name: String): Collection<CallableDescriptor> {
|
||||
val javaDeclarations = PsiShortNamesCache.getInstance(project).getFieldsByName(name, scope).asSequence() +
|
||||
PsiShortNamesCache.getInstance(project).getMethodsByName(name, scope).asSequence()
|
||||
val javaDeclarations = PsiShortNamesCache.getInstance(project).getFieldsByName(name, scopeWithoutKotlin).asSequence() +
|
||||
PsiShortNamesCache.getInstance(project).getMethodsByName(name, scopeWithoutKotlin).asSequence()
|
||||
return javaDeclarations
|
||||
.filterNot { it is KtLightElement<*,*> }
|
||||
.mapNotNull { (it as PsiMember).getJavaMemberDescriptor(resolutionFacade) as? CallableDescriptor }
|
||||
.filter(descriptorFilter)
|
||||
.toSet()
|
||||
@@ -298,11 +306,11 @@ class KotlinIndicesHelper(
|
||||
val shortNamesCache = PsiShortNamesCache.getInstance(project)
|
||||
|
||||
val allMethodNames = hashSetOf<String>()
|
||||
shortNamesCache.processAllMethodNames({ name -> if (nameFilter(name)) allMethodNames.add(name); true }, scope, idFilter)
|
||||
shortNamesCache.processAllMethodNames({ name -> if (nameFilter(name)) allMethodNames.add(name); true }, scopeWithoutKotlin, idFilter)
|
||||
for (name in allMethodNames) {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
for (method in shortNamesCache.getMethodsByName(name, scope)) {
|
||||
for (method in shortNamesCache.getMethodsByName(name, scopeWithoutKotlin).filterNot { it is KtLightElement<*, *> }) {
|
||||
if (!method.hasModifierProperty(PsiModifier.STATIC)) continue
|
||||
if (filterOutPrivate && method.hasModifierProperty(PsiModifier.PRIVATE)) continue
|
||||
if (method.containingClass?.parent !is PsiFile) continue // only top-level classes
|
||||
@@ -321,11 +329,11 @@ class KotlinIndicesHelper(
|
||||
}
|
||||
|
||||
val allFieldNames = hashSetOf<String>()
|
||||
shortNamesCache.processAllFieldNames({ name -> if (nameFilter(name)) allFieldNames.add(name); true }, scope, idFilter)
|
||||
shortNamesCache.processAllFieldNames({ name -> if (nameFilter(name)) allFieldNames.add(name); true }, scopeWithoutKotlin, idFilter)
|
||||
for (name in allFieldNames) {
|
||||
ProgressManager.checkCanceled()
|
||||
|
||||
for (field in shortNamesCache.getFieldsByName(name, scope)) {
|
||||
for (field in shortNamesCache.getFieldsByName(name, scopeWithoutKotlin).filterNot { it is KtLightElement<*, *> }) {
|
||||
if (!field.hasModifierProperty(PsiModifier.STATIC)) continue
|
||||
if (filterOutPrivate && field.hasModifierProperty(PsiModifier.PRIVATE)) continue
|
||||
val descriptor = field.getJavaFieldDescriptor() ?: continue
|
||||
|
||||
@@ -24,10 +24,12 @@ import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.stubs.StubIndex
|
||||
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||
import org.jetbrains.kotlin.idea.decompiler.builtIns.KotlinBuiltInFileType
|
||||
import org.jetbrains.kotlin.idea.stubindex.*
|
||||
import org.jetbrains.kotlin.psi.KtEnumEntry
|
||||
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||
import java.util.*
|
||||
|
||||
class KotlinGotoClassContributor : GotoClassContributor {
|
||||
@@ -78,8 +80,14 @@ class KotlinGotoSymbolContributor : ChooseByNameContributor {
|
||||
val noLibrarySourceScope = KotlinSourceFilterScope.projectSourceAndClassFiles(baseScope, project)
|
||||
|
||||
val result = ArrayList<NavigationItem>()
|
||||
result += KotlinFunctionShortNameIndex.getInstance().get(name, project, noLibrarySourceScope)
|
||||
result += KotlinPropertyShortNameIndex.getInstance().get(name, project, noLibrarySourceScope)
|
||||
result += KotlinFunctionShortNameIndex.getInstance().get(name, project, noLibrarySourceScope).filter {
|
||||
val method = LightClassUtil.getLightClassMethod(it)
|
||||
method == null || it.name != method.name
|
||||
}
|
||||
result += KotlinPropertyShortNameIndex.getInstance().get(name, project, noLibrarySourceScope).filter {
|
||||
LightClassUtil.getLightClassBackingField(it) == null ||
|
||||
it.containingClass()?.isInterface() ?: false
|
||||
}
|
||||
result += KotlinClassShortNameIndex.getInstance().get(name, project, BuiltInClassesScope(noLibrarySourceScope))
|
||||
result += KotlinTypeAliasShortNameIndex.getInstance().get(name, project, noLibrarySourceScope)
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
object B1 {
|
||||
@JvmStatic
|
||||
fun foobar() {}
|
||||
|
||||
@JvmField
|
||||
val barfoo = ""
|
||||
}
|
||||
object B2 {
|
||||
@JvmStatic
|
||||
fun foobar() {}
|
||||
|
||||
@JvmField
|
||||
val barfoo = ""
|
||||
}
|
||||
object B3 {
|
||||
@JvmStatic
|
||||
fun foobar() {}
|
||||
|
||||
@JvmField
|
||||
val barfoo = ""
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
object B1 {
|
||||
@JvmField
|
||||
val foobar = ""
|
||||
|
||||
fun method1(){}
|
||||
|
||||
fun methodInBoth(){}
|
||||
}
|
||||
|
||||
object B2 {
|
||||
val barfoo = ""
|
||||
|
||||
fun method2(){}
|
||||
|
||||
fun methodInBoth(){}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class C1 {
|
||||
|
||||
}
|
||||
|
||||
object O1 {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
@file:JvmName("KotlinShortNameCacheTestData")
|
||||
|
||||
var topLevelVar: String
|
||||
get() {
|
||||
return ""
|
||||
}
|
||||
set(value) {
|
||||
}
|
||||
|
||||
|
||||
object B1 {
|
||||
@JvmStatic
|
||||
var staticObjectVar: String
|
||||
get() {
|
||||
return ""
|
||||
}
|
||||
set(value) {
|
||||
}
|
||||
|
||||
var nonStaticObjectVar: String
|
||||
get() {
|
||||
return ""
|
||||
}
|
||||
set(value) {
|
||||
}
|
||||
}
|
||||
|
||||
class C1 {
|
||||
var classVar: String
|
||||
get() {
|
||||
return ""
|
||||
}
|
||||
set(value) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
var staticCompanionVar: String
|
||||
get() {
|
||||
return ""
|
||||
}
|
||||
set(value) {
|
||||
}
|
||||
|
||||
var nonStaticCompanionVar: String
|
||||
get() {
|
||||
return ""
|
||||
}
|
||||
set(value) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
@file:JvmName("KotlinShortNameCacheTestData")
|
||||
|
||||
var topLevelVar = ""
|
||||
|
||||
|
||||
object B1 {
|
||||
@JvmStatic
|
||||
var staticObjectVar = ""
|
||||
|
||||
var nonStaticObjectVar = ""
|
||||
}
|
||||
|
||||
class C1 {
|
||||
var classVar = ""
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
var staticCompanionVar = ""
|
||||
|
||||
var nonStaticCompanionVar = ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
@JvmField
|
||||
var topLevelVar = ""
|
||||
|
||||
object B1 {
|
||||
@JvmField
|
||||
var objectVar = ""
|
||||
}
|
||||
|
||||
class C1 {
|
||||
@JvmField
|
||||
var classVar = ""
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
var companionVar = ""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
fun topLevelFunction(){
|
||||
|
||||
}
|
||||
|
||||
object B1 {
|
||||
@JvmStatic
|
||||
fun staticMethodOfObject() {
|
||||
}
|
||||
|
||||
fun nonStaticMethodOfObject() {
|
||||
}
|
||||
}
|
||||
|
||||
class C1 {
|
||||
fun methodOfClass() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun staticMethodOfCompanion() {
|
||||
}
|
||||
|
||||
fun nonStaticMethodOfCompanion() {
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import constant 'foo.Bar.Companion.foobar'" "true"
|
||||
// ERROR: Unresolved reference: foobar
|
||||
// ACTION: Rename reference
|
||||
// ACTION: Create field 'foobar'
|
||||
// ACTION: Create parameter 'foobar'
|
||||
// ACTION: Create local variable 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
foobar<caret>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
companion object {
|
||||
@JvmField var foobar = "foobar"
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import constant 'foo.Bar.Companion.foobar'" "true"
|
||||
// ERROR: Unresolved reference: foobar
|
||||
// ACTION: Rename reference
|
||||
// ACTION: Create field 'foobar'
|
||||
// ACTION: Create parameter 'foobar'
|
||||
// ACTION: Create local variable 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.Companion.foobar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
foobar<caret>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.foobar'" "true"
|
||||
// ERROR: Unresolved reference: foobar
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
foobar<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
class Bar {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun foobar() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.foobar'" "true"
|
||||
// ERROR: Unresolved reference: foobar
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.foobar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
foobar<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.getValue'" "true"
|
||||
// ERROR: Unresolved reference: getValue
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
getValue<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
companion object {
|
||||
@JvmStatic val value = "foobar";
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.getValue'" "true"
|
||||
// ERROR: Unresolved reference: getValue
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.getValue;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
getValue<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+41
@@ -0,0 +1,41 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.setVariable'" "true"
|
||||
// ERROR: Unresolved reference: setVariable
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
setVariable<caret>("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
companion object {
|
||||
@JvmStatic var variable: String;
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.setVariable'" "true"
|
||||
// ERROR: Unresolved reference: setVariable
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.setVariable;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
setVariable<caret>("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+43
@@ -0,0 +1,43 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.getValue'" "true"
|
||||
// ERROR: Unresolved reference: getValue
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
getValue<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
companion object {
|
||||
val value = "foobar";
|
||||
@JvmStatic get() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.getValue'" "true"
|
||||
// ERROR: Unresolved reference: getValue
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.getValue;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
getValue<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+44
@@ -0,0 +1,44 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.setVariable'" "true"
|
||||
// ERROR: Unresolved reference: setVariable
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
setVariable<caret>("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
companion object {
|
||||
var variable: String;
|
||||
@JvmStatic set(value) {
|
||||
field = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.setVariable'" "true"
|
||||
// ERROR: Unresolved reference: setVariable
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.setVariable;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
setVariable<caret>("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import constant 'foo.Bar.foobar'" "true"
|
||||
// ERROR: Unresolved reference: foobar
|
||||
// ACTION: Rename reference
|
||||
// ACTION: Create field 'foobar'
|
||||
// ACTION: Create parameter 'foobar'
|
||||
// ACTION: Create local variable 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
foobar<caret>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
@JvmField var foobar = "foobar"
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import constant 'foo.Bar.foobar'" "true"
|
||||
// ERROR: Unresolved reference: foobar
|
||||
// ACTION: Rename reference
|
||||
// ACTION: Create field 'foobar'
|
||||
// ACTION: Create parameter 'foobar'
|
||||
// ACTION: Create local variable 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.foobar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
foobar<caret>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.foobar'" "true"
|
||||
// ERROR: Unresolved reference: foobar
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
foobar<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
@JvmStatic fun foobar() {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.foobar'" "true"
|
||||
// ERROR: Unresolved reference: foobar
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.foobar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
foobar<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.getValue'" "true"
|
||||
// ERROR: Unresolved reference: getValue
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
getValue<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
@JvmStatic val value = "foobar";
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.getValue'" "true"
|
||||
// ERROR: Unresolved reference: getValue
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.getValue;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
getValue<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.setVariable'" "true"
|
||||
// ERROR: Unresolved reference: setVariable
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
setVariable<caret>("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
@JvmStatic var variable: String;
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.setVariable'" "true"
|
||||
// ERROR: Unresolved reference: setVariable
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.setVariable;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
setVariable<caret>("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.getValue'" "true"
|
||||
// ERROR: Unresolved reference: getValue
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
getValue<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
val value = "foobar";
|
||||
@JvmStatic get() {
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.getValue'" "true"
|
||||
// ERROR: Unresolved reference: getValue
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.getValue;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
getValue<caret>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
// FILE: bar/Foo.before.java
|
||||
// "Static import method 'foo.Bar.setVariable'" "true"
|
||||
// ERROR: Unresolved reference: setVariable
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
setVariable<caret>("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FILE: foo/Bar.dependency.kt
|
||||
package foo
|
||||
|
||||
object Bar {
|
||||
var variable: String;
|
||||
@JvmStatic set(value) {
|
||||
field = value
|
||||
}
|
||||
}
|
||||
|
||||
// FILE: bar/Foo.after.java
|
||||
// "Static import method 'foo.Bar.setVariable'" "true"
|
||||
// ERROR: Unresolved reference: setVariable
|
||||
// ACTION: Create method 'foobar'
|
||||
// WITH_RUNTIME
|
||||
package bar;
|
||||
|
||||
import static foo.Bar.setVariable;
|
||||
|
||||
public class Foo {
|
||||
public void main()
|
||||
{
|
||||
setVariable<caret>("foobar");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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
|
||||
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.psi.PsiField
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.psi.PsiModifier
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.PsiShortNamesCache
|
||||
import com.sun.tools.javac.util.Convert.shortName
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightField
|
||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
|
||||
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
|
||||
import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase
|
||||
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
|
||||
class KotlinShortNamesCacheTest : KotlinCodeInsightTestCase() {
|
||||
|
||||
lateinit var cacheInstance: PsiShortNamesCache
|
||||
|
||||
override fun setUp() {
|
||||
super.setUp()
|
||||
cacheInstance = KotlinShortNamesCache(project)
|
||||
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, testProjectJdk)
|
||||
}
|
||||
|
||||
override fun tearDown() {
|
||||
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(myModule, testProjectJdk)
|
||||
super.tearDown()
|
||||
|
||||
}
|
||||
|
||||
override fun getModule() = myModule!!
|
||||
|
||||
fun testGetMethodsByNameIfNotMoreThanLimits() {
|
||||
val file = KotlinTestUtils.navigationMetadata("idea/testData/cache/kotlinShortNamesCacheTestData1.kt")
|
||||
configureByFile(file)
|
||||
val scope = GlobalSearchScope.allScope(project)
|
||||
assertSize(2, cacheInstance.getMethodsByNameIfNotMoreThan("foobar", scope, 2))
|
||||
assertSize(3, cacheInstance.getMethodsByNameIfNotMoreThan("foobar", scope, 3))
|
||||
assertSize(3, cacheInstance.getMethodsByNameIfNotMoreThan("foobar", scope, Int.MAX_VALUE))
|
||||
}
|
||||
|
||||
fun testGetFieldsByNameIfNotMoreThanLimits() {
|
||||
val file = KotlinTestUtils.navigationMetadata("idea/testData/cache/kotlinShortNamesCacheTestData1.kt")
|
||||
configureByFile(file)
|
||||
val scope = GlobalSearchScope.allScope(project)
|
||||
assertSize(2, cacheInstance.getFieldsByNameIfNotMoreThan("barfoo", scope, 2))
|
||||
assertSize(3, cacheInstance.getFieldsByNameIfNotMoreThan("barfoo", scope, 3))
|
||||
assertSize(3, cacheInstance.getFieldsByNameIfNotMoreThan("barfoo", scope, Int.MAX_VALUE))
|
||||
}
|
||||
|
||||
fun testGetAllFields() {
|
||||
val file = KotlinTestUtils.navigationMetadata("idea/testData/cache/kotlinShortNamesCacheTestData2.kt")
|
||||
configureByFile(file)
|
||||
val allFieldNameList = cacheInstance.allFieldNames.asList()
|
||||
assertContainsElements(allFieldNameList, "foobar")
|
||||
assertContainsElements(allFieldNameList, "barfoo")
|
||||
}
|
||||
|
||||
fun testGetAllMethods() {
|
||||
val file = KotlinTestUtils.navigationMetadata("idea/testData/cache/kotlinShortNamesCacheTestData2.kt")
|
||||
configureByFile(file)
|
||||
val allMethodNameList = cacheInstance.allMethodNames.asList()
|
||||
assertContainsElements(allMethodNameList, "getFoobar")
|
||||
assertContainsElements(allMethodNameList, "getBarfoo")
|
||||
assertContainsElements(allMethodNameList, "setFoobar")
|
||||
assertContainsElements(allMethodNameList, "setBarfoo")
|
||||
assertContainsElements(allMethodNameList, "method1")
|
||||
assertContainsElements(allMethodNameList, "method2")
|
||||
assertContainsElements(allMethodNameList, "methodInBoth")
|
||||
}
|
||||
|
||||
fun testGetAllClasses() {
|
||||
val file = KotlinTestUtils.navigationMetadata("idea/testData/cache/kotlinShortNamesCacheTestDataClasses.kt")
|
||||
configureByFile(file)
|
||||
val allClassNameList = cacheInstance.allClassNames.asList()
|
||||
assertContainsElements(allClassNameList, "C1")
|
||||
assertContainsElements(allClassNameList, "O1")
|
||||
}
|
||||
|
||||
fun methodArrayDebugToString(a: Array<PsiMethod>)
|
||||
= a.map { "${(it as KtLightMethod).clsDelegate.getKotlinFqName()} static=${it.hasModifierProperty(PsiModifier.STATIC)}" }.joinToString("\n")
|
||||
|
||||
fun accessorArrayDebugToString(a: Array<PsiMethod>)
|
||||
= a.map { "${(it as KtLightMethod).clsDelegate.getKotlinFqName()} property=${(it.lightMethodOrigin?.originalElement as KtProperty).fqName} static=${it.hasModifierProperty(PsiModifier.STATIC)}" }.joinToString("\n")
|
||||
|
||||
fun checkMethodFound(methods: Array<PsiMethod>, stringFqName: String, static: Boolean) {
|
||||
assertNotNull("Method $stringFqName with static=$static not found\n" + methodArrayDebugToString(methods),
|
||||
methods.find {
|
||||
stringFqName == (it as KtLightMethod).clsDelegate.getKotlinFqName().toString()
|
||||
&&
|
||||
it.hasModifierProperty(PsiModifier.STATIC) == static
|
||||
})
|
||||
}
|
||||
|
||||
fun checkIsSingleMethodFound(scope: GlobalSearchScope, stringFqName: String, static: Boolean, query: String = shortName(stringFqName)) {
|
||||
cacheInstance.getMethodsByName(query, scope).let {
|
||||
checkMethodFound(it, stringFqName, static)
|
||||
assertSize(1, it)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkIsSingleMethodFoundCompanion(scope: GlobalSearchScope, delegateFqName: String, originalFqName: String, query: String = shortName(originalFqName)) {
|
||||
cacheInstance.getMethodsByName(query, scope).let {
|
||||
checkMethodFound(it, delegateFqName, true)
|
||||
checkMethodFound(it, originalFqName, false)
|
||||
assertEquals((it[0] as KtLightMethod).kotlinOrigin, (it[1] as KtLightMethod).kotlinOrigin)
|
||||
assertSize(2, it)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkIsVarAccessorsFound(scope: GlobalSearchScope, stringVarFqName: String, getFqName: String, setFqName: String, static: Boolean) {
|
||||
val varName = shortName(stringVarFqName)
|
||||
|
||||
cacheInstance.getMethodsByName(JvmAbi.getterName(varName), scope).let {
|
||||
checkAccessorFound(it, getFqName, stringVarFqName, static)
|
||||
assertSize(1, it)
|
||||
}
|
||||
cacheInstance.getMethodsByName(JvmAbi.setterName(varName), scope).let {
|
||||
checkAccessorFound(it, setFqName, stringVarFqName, static)
|
||||
assertSize(1, it)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkIsVarAccessorsFound(scope: GlobalSearchScope, stringVarFqName: String, static: Boolean) {
|
||||
val (getter, setter) = accessorsFqNameStringFor(stringVarFqName)
|
||||
checkIsVarAccessorsFound(scope, stringVarFqName, getter, setter, static)
|
||||
}
|
||||
|
||||
fun checkIsVarAccessorsFoundCompanion(scope: GlobalSearchScope, stringVarFqName: String, getterFqName: String, setterFqName: String,
|
||||
delegateGetterFqName: String, delegateSetterFqName: String) {
|
||||
val varName = shortName(stringVarFqName)
|
||||
|
||||
|
||||
cacheInstance.getMethodsByName(JvmAbi.getterName(varName), scope).let {
|
||||
checkAccessorFound(it, delegateGetterFqName, stringVarFqName, true)
|
||||
checkAccessorFound(it, getterFqName, stringVarFqName, false)
|
||||
assertSize(2, it)
|
||||
}
|
||||
cacheInstance.getMethodsByName(JvmAbi.setterName(varName), scope).let {
|
||||
checkAccessorFound(it, delegateSetterFqName, stringVarFqName, true)
|
||||
checkAccessorFound(it, setterFqName, stringVarFqName, false)
|
||||
assertSize(2, it)
|
||||
}
|
||||
}
|
||||
|
||||
fun checkIsVarAccessorsFoundCompanion(scope: GlobalSearchScope, stringVarFqName: String) {
|
||||
val (getter, setter) = accessorsFqNameStringFor(stringVarFqName)
|
||||
val varFqName = FqName(stringVarFqName)
|
||||
val varName = varFqName.shortName().asString()
|
||||
val companionParent = varFqName.parent().parent().asString()
|
||||
|
||||
checkIsVarAccessorsFoundCompanion(scope, stringVarFqName, getter, setter,
|
||||
companionParent + "." + JvmAbi.getterName(varName),
|
||||
companionParent + "." + JvmAbi.setterName(varName))
|
||||
}
|
||||
|
||||
fun accessorsFqNameStringFor(stringVarFqName: String): Pair<String, String> {
|
||||
val varFqName = FqName(stringVarFqName)
|
||||
val varShortName = varFqName.shortName().asString()
|
||||
val stringVarParentFqName = varFqName.parent().asString()
|
||||
return Pair(stringVarParentFqName + "." + JvmAbi.getterName(varShortName),
|
||||
stringVarParentFqName + "." + JvmAbi.setterName(varShortName))
|
||||
}
|
||||
|
||||
fun checkAccessorFound(methods: Array<PsiMethod>, stringFqName: String, propertyFqName: String, static: Boolean) {
|
||||
assertNotNull("Accessor $stringFqName property=$propertyFqName static=$static not found\n" + accessorArrayDebugToString(methods),
|
||||
methods.find {
|
||||
stringFqName == (it as KtLightMethod).clsDelegate.getKotlinFqName().toString()
|
||||
&&
|
||||
(it.lightMethodOrigin?.originalElement as KtProperty).fqName?.asString() == propertyFqName
|
||||
&&
|
||||
it.hasModifierProperty(PsiModifier.STATIC) == static
|
||||
})
|
||||
}
|
||||
|
||||
fun testGetMethodsByNameWithFunctions() {
|
||||
val file = KotlinTestUtils.navigationMetadata("idea/testData/cache/kotlinShortNamesCacheTestDataMethods.kt")
|
||||
configureByFile(file)
|
||||
val scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)
|
||||
checkIsSingleMethodFound(scope, "KotlinShortNamesCacheTestDataMethodsKt.topLevelFunction", true)
|
||||
checkIsSingleMethodFound(scope, "B1.staticMethodOfObject", true)
|
||||
checkIsSingleMethodFound(scope, "B1.nonStaticMethodOfObject", false)
|
||||
checkIsSingleMethodFound(scope, "C1.methodOfClass", false)
|
||||
checkIsSingleMethodFoundCompanion(scope, "C1.staticMethodOfCompanion", "C1.Companion.staticMethodOfCompanion")
|
||||
checkIsSingleMethodFound(scope, "C1.Companion.nonStaticMethodOfCompanion", false)
|
||||
}
|
||||
|
||||
fun doTestGetMethodsByNameWithAccessors(file: String) {
|
||||
|
||||
configureByFile(file)
|
||||
val scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)
|
||||
checkIsVarAccessorsFound(scope, "topLevelVar", "KotlinShortNameCacheTestData.getTopLevelVar",
|
||||
"KotlinShortNameCacheTestData.setTopLevelVar", true)
|
||||
|
||||
checkIsVarAccessorsFound(scope, "B1.staticObjectVar", true)
|
||||
checkIsVarAccessorsFound(scope, "B1.nonStaticObjectVar", false)
|
||||
checkIsVarAccessorsFound(scope, "C1.classVar", false)
|
||||
checkIsVarAccessorsFoundCompanion(scope, "C1.Companion.staticCompanionVar")
|
||||
checkIsVarAccessorsFound(scope, "C1.Companion.nonStaticCompanionVar", false)
|
||||
}
|
||||
|
||||
fun testGetMethodsByNameWithDefaultPropertyAccessors() {
|
||||
val file = KotlinTestUtils.navigationMetadata("idea/testData/cache/kotlinShortNamesCacheTestDataDefaultProperties.kt")
|
||||
doTestGetMethodsByNameWithAccessors(file)
|
||||
}
|
||||
|
||||
fun testGetMethodsByNameWithCustomPropertyAccessors() {
|
||||
val file = KotlinTestUtils.navigationMetadata("idea/testData/cache/kotlinShortNamesCacheTestDataCustomProperties.kt")
|
||||
doTestGetMethodsByNameWithAccessors(file)
|
||||
}
|
||||
|
||||
fun checkFieldFound(methods: Array<PsiField>, stringFqName: String, static: Boolean) {
|
||||
assertNotNull("Field $stringFqName with static=$static not found\n" + fieldArrayDebugToString(methods),
|
||||
methods.find {
|
||||
stringFqName == (it as KtLightField).clsDelegate.getKotlinFqName().toString()
|
||||
&&
|
||||
it.hasModifierProperty(PsiModifier.STATIC) == static
|
||||
})
|
||||
}
|
||||
|
||||
fun fieldArrayDebugToString(a: Array<PsiField>)
|
||||
= a.map { "${(it as KtLightField).clsDelegate.getKotlinFqName()} property=${(it.kotlinOrigin as KtProperty).fqName} static=${it.hasModifierProperty(PsiModifier.STATIC)}" }.joinToString("\n")
|
||||
|
||||
|
||||
fun checkIsSingleFieldFound(scope: GlobalSearchScope, stringFqName: String, static: Boolean, query: String = shortName(stringFqName)) {
|
||||
cacheInstance.getFieldsByName(query, scope).let {
|
||||
checkFieldFound(it, stringFqName, static)
|
||||
assertSize(1, it)
|
||||
}
|
||||
}
|
||||
|
||||
fun testGetFieldsByName() {
|
||||
val file = KotlinTestUtils.navigationMetadata("idea/testData/cache/kotlinShortNamesCacheTestDataFields.kt")
|
||||
configureByFile(file)
|
||||
val scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)
|
||||
checkIsSingleFieldFound(scope, "KotlinShortNamesCacheTestDataFieldsKt.topLevelVar", true)
|
||||
checkIsSingleFieldFound(scope, "B1.objectVar", true)
|
||||
checkIsSingleFieldFound(scope, "C1.classVar", false)
|
||||
checkIsSingleFieldFound(scope, "C1.companionVar", true)
|
||||
}
|
||||
|
||||
|
||||
override fun getTestProjectJdk(): Sdk? {
|
||||
return PluginTestCaseBase.mockJdk()
|
||||
}
|
||||
|
||||
override fun getTestDataPath(): String {
|
||||
return KotlinTestUtils.getHomeDirectory() + "/"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -167,6 +167,78 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinCompanionPropertyAsFieldFromJava.test")
|
||||
public void testImportKotlinCompanionPropertyAsFieldFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinCompanionPropertyAsFieldFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinCompanionStaticFunctionFromJava.test")
|
||||
public void testImportKotlinCompanionStaticFunctionFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinCompanionStaticFunctionFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinCompanionStaticPropertyDefaultGetterFromJava.test")
|
||||
public void testImportKotlinCompanionStaticPropertyDefaultGetterFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinCompanionStaticPropertyDefaultGetterFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinCompanionStaticPropertyDefaultSetterFromJava.test")
|
||||
public void testImportKotlinCompanionStaticPropertyDefaultSetterFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinCompanionStaticPropertyDefaultSetterFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinCompanionStaticPropertyOverloadedGetterFromJava.test")
|
||||
public void testImportKotlinCompanionStaticPropertyOverloadedGetterFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinCompanionStaticPropertyOverloadedGetterFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinCompanionStaticPropertyOverloadedSetterFromJava.test")
|
||||
public void testImportKotlinCompanionStaticPropertyOverloadedSetterFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinCompanionStaticPropertyOverloadedSetterFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinPropertyAsFieldFromJava.test")
|
||||
public void testImportKotlinPropertyAsFieldFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinPropertyAsFieldFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinStaticFunctionFromJava.test")
|
||||
public void testImportKotlinStaticFunctionFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinStaticFunctionFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinStaticPropertyDefaultGetterFromJava.test")
|
||||
public void testImportKotlinStaticPropertyDefaultGetterFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinStaticPropertyDefaultGetterFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinStaticPropertyDefaultSetterFromJava.test")
|
||||
public void testImportKotlinStaticPropertyDefaultSetterFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinStaticPropertyDefaultSetterFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinStaticPropertyOverloadedGetterFromJava.test")
|
||||
public void testImportKotlinStaticPropertyOverloadedGetterFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinStaticPropertyOverloadedGetterFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importKotlinStaticPropertyOverloadedSetterFromJava.test")
|
||||
public void testImportKotlinStaticPropertyOverloadedSetterFromJava() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importKotlinStaticPropertyOverloadedSetterFromJava.test");
|
||||
doTestWithExtraFile(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("importTrait.before.Main.kt")
|
||||
public void testImportTrait() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/importTrait.before.Main.kt");
|
||||
|
||||
Reference in New Issue
Block a user