Changes on review of pull request

This commit is contained in:
Valentin Kipyatkov
2016-08-17 16:37:06 +03:00
parent 939b4768f5
commit 0072bf079d
5 changed files with 103 additions and 58 deletions
@@ -16,7 +16,6 @@ remove.unnecessary.non.null.assertion=Remove unnecessary non-null assertion (!!)
change.to.backing.field=Change reference to backing field
implement.members=Implement members
import.fix=Import
import.static.fix=Static import
imports.chooser.title=Imports
rename.kotlin.package.class.error=Can't rename Kotlin package facade class
add.semicolon.after.invocation=Add semicolon after invocation of ''{0}''
@@ -205,32 +205,29 @@ class KotlinIndicesHelper(
.toSet()
}
fun getJvmStatics(name: String): Collection<DeclarationDescriptor> {
return sequenceOf(PsiShortNamesCache.getInstance(project).getFieldsByName(name, scope),
PsiShortNamesCache.getInstance(project).getMethodsByName(name, scope))
.flatMap { it.asSequence() }
.mapNotNull { (it as PsiMember).getJavaMemberDescriptor(resolutionFacade) }
fun getJvmCallablesByName(name: String): Collection<CallableDescriptor> {
val javaDeclarations = PsiShortNamesCache.getInstance(project).getFieldsByName(name, scope).asSequence() +
PsiShortNamesCache.getInstance(project).getMethodsByName(name, scope).asSequence()
return javaDeclarations
.mapNotNull { (it as PsiMember).getJavaMemberDescriptor(resolutionFacade) as? CallableDescriptor }
.filter(descriptorFilter)
.toSet()
}
fun getKotlinStatics(name: String): Collection<DeclarationDescriptor> {
return sequenceOf(KotlinFunctionShortNameIndex.getInstance().get(name, project, scope),
KotlinPropertyShortNameIndex.getInstance().get(name, project, scope))
.flatMap { it.asSequence() }
.mapNotNull {
when (it) {
is KtNamedFunction -> it.descriptor
is KtProperty -> it.descriptor
else -> null
}
}.filterNot { it.importableFqName == null }
fun getKotlinCallablesByName(name: String): Collection<CallableDescriptor> {
val functions = KotlinFunctionShortNameIndex.getInstance().get(name, project, scope)
.asSequence()
.map { it.descriptor as? CallableDescriptor }
val properties = KotlinPropertyShortNameIndex.getInstance().get(name, project, scope)
.asSequence()
.map { it.descriptor as? CallableDescriptor }
return (functions + properties)
.filterNotNull()
.filter(descriptorFilter)
.toSet()
}
fun getKotlinClasses(nameFilter: (String) -> Boolean, kindFilter: (ClassKind) -> Boolean): Collection<ClassDescriptor> {
return KotlinFullClassNameIndex.getInstance().getAllKeys(project).asSequence()
.map { FqName(it) }
@@ -29,6 +29,7 @@ import com.intellij.psi.PsiFile
import com.intellij.psi.util.PsiModificationTracker
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithVisibility
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
import org.jetbrains.kotlin.diagnostics.Errors
@@ -42,6 +43,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.getResolveScope
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.core.KotlinIndicesHelper
import org.jetbrains.kotlin.idea.core.isVisible
import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
import org.jetbrains.kotlin.name.Name
@@ -147,8 +149,7 @@ internal abstract class AutoImportFixBase<T : KtExpression>(expression: T) :
val indicesHelper = KotlinIndicesHelper(resolutionFacade, searchScope, ::isVisible)
val result = fillCandidates(callTypeAndReceiver, file, bindingContext,
indicesHelper, nameStr, filterByCallType = { callTypeAndReceiver.callType.descriptorKindFilter.accepts(it) })
val result = fillCandidates(nameStr, callTypeAndReceiver, bindingContext, indicesHelper)
return if (result.size > 1)
reduceCandidatesBasedOnDependencyRuleViolation(result, file)
@@ -156,9 +157,12 @@ internal abstract class AutoImportFixBase<T : KtExpression>(expression: T) :
result
}
abstract fun fillCandidates(callTypeAndReceiver: CallTypeAndReceiver<*, *>, file: KtFile,
bindingContext: BindingContext, indicesHelper: KotlinIndicesHelper,
nameStr: String, filterByCallType: (descriptor: DeclarationDescriptor) -> (Boolean)): List<DeclarationDescriptor>
abstract fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor>
private fun reduceCandidatesBasedOnDependencyRuleViolation(
candidates: Collection<DeclarationDescriptor>, file: PsiFile): Collection<DeclarationDescriptor> {
@@ -172,25 +176,32 @@ internal abstract class AutoImportFixBase<T : KtExpression>(expression: T) :
}
internal abstract class AutoImportFixBaseDynamicContext<T : KtExpression>(expression: T) : AutoImportFixBase<T>(expression) {
override fun fillCandidates(callTypeAndReceiver: CallTypeAndReceiver<*, *>, file: KtFile, bindingContext: BindingContext, indicesHelper: KotlinIndicesHelper, nameStr: String, filterByCallType: (DeclarationDescriptor) -> Boolean): List<DeclarationDescriptor> {
override fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val result = ArrayList<DeclarationDescriptor>()
val expression = element
if (expression is KtSimpleNameExpression) {
if (!expression.isImportDirectiveExpression() && !KtPsiUtil.isSelectorInQualified(expression)) {
if (ProjectStructureUtil.isJsKotlinModule(file)) {
indicesHelper.getKotlinClasses({ it == nameStr }, { true }).filterTo(result, filterByCallType)
val filterByCallType = { descriptor: DeclarationDescriptor -> callTypeAndReceiver.callType.descriptorKindFilter.accepts(descriptor) }
if (ProjectStructureUtil.isJsKotlinModule(expression.getContainingKtFile())) {
indicesHelper.getKotlinClasses({ it == name }, { true }).filterTo(result, filterByCallType)
}
else {
indicesHelper.getJvmClassesByName(nameStr).filterTo(result, filterByCallType)
indicesHelper.getJvmClassesByName(name).filterTo(result, filterByCallType)
}
indicesHelper.getTopLevelCallablesByName(nameStr).filterTo(result, filterByCallType)
indicesHelper.getTopLevelCallablesByName(name).filterTo(result, filterByCallType)
}
}
result.addAll(indicesHelper.getCallableTopLevelExtensions(callTypeAndReceiver, expression, bindingContext) { it == nameStr })
result.addAll(indicesHelper.getCallableTopLevelExtensions(callTypeAndReceiver, expression, bindingContext) { it == name })
return result
}
@@ -366,16 +377,28 @@ internal class MissingComponentsAutoImportFix(element: KtExpression, override va
internal class AutoImportStaticFix(expression: KtSimpleNameExpression) : AutoImportFixBase<KtSimpleNameExpression>(expression) {
override fun getText() = KotlinBundle.message("import.static.fix")
override fun getText() = "Static import"
override fun fillCandidates(callTypeAndReceiver: CallTypeAndReceiver<*, *>, file: KtFile, bindingContext: BindingContext, indicesHelper: KotlinIndicesHelper, nameStr: String, filterByCallType: (DeclarationDescriptor) -> Boolean): List<DeclarationDescriptor> {
override fun fillCandidates(
name: String,
callTypeAndReceiver: CallTypeAndReceiver<*, *>,
bindingContext: BindingContext,
indicesHelper: KotlinIndicesHelper
): List<DeclarationDescriptor> {
val result = ArrayList<DeclarationDescriptor>()
val expression = element
if (expression is KtSimpleNameExpression) {
if (!expression.isImportDirectiveExpression() && !KtPsiUtil.isSelectorInQualified(expression)) {
indicesHelper.getKotlinStatics(nameStr).filterTo(result, filterByCallType)
if (!(ProjectStructureUtil.isJsKotlinModule(file))) {
indicesHelper.getJvmStatics(nameStr).filterTo(result, filterByCallType)
val filterByCallType = { descriptor: DeclarationDescriptor -> callTypeAndReceiver.callType.descriptorKindFilter.accepts(descriptor) }
indicesHelper.getKotlinCallablesByName(name)
.filter { it.canBeReferencedViaImport() && it.containingDeclaration !is PackageFragmentDescriptor }
.filterTo(result, filterByCallType)
if (!ProjectStructureUtil.isJsKotlinModule(expression.getContainingKtFile())) {
indicesHelper.getJvmCallablesByName(name)
.filter { it.canBeReferencedViaImport() }
.filterTo(result, filterByCallType)
}
}
}
@@ -385,28 +408,18 @@ internal class AutoImportStaticFix(expression: KtSimpleNameExpression) : AutoImp
override fun getCallTypeAndReceiver() = CallTypeAndReceiver.detect(element)
override val importNames: Collection<Name> = run {
if (element.getIdentifier() == null) {
val conventionName = KtPsiUtil.getConventionName(element)
if (conventionName != null) {
if (element is KtOperationReferenceExpression) {
val elementType = element.firstChild.node.elementType
if (elementType in OperatorConventions.ASSIGNMENT_OPERATIONS) {
val counterpart = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS[elementType]
val counterpartName = OperatorConventions.BINARY_OPERATION_NAMES[counterpart]
if (counterpartName != null) {
return@run listOf(conventionName, counterpartName)
}
}
}
return@run conventionName.singletonOrEmptyList()
if (element.getIdentifier() != null) {
val name = element.getReferencedName()
if (Name.isValidIdentifier(name)) {
Name.identifier(name).singletonList()
}
else {
emptyList<Name>()
}
}
else if (Name.isValidIdentifier(element.getReferencedName())) {
return@run Name.identifier(element.getReferencedName()).singletonOrEmptyList()
else {
emptyList<Name>()
}
emptyList<Name>()
}
override fun getSupportedErrors(): Collection<DiagnosticFactory<*>> = ERRORS
@@ -0,0 +1,32 @@
// FILE: main.before.kt
// "Static import" "false"
// ERROR: Unresolved reference: foobar
// ACTION: Create function 'foobar'
// ACTION: Import
// ACTION: Rename reference
//KT-9009
fun f() {
foobar<caret>()
}
//FILE: dependency.before.kt
package bar
fun foobar() {
}
//FILE: main.after.kt
// "Static import" "false"
// ERROR: Unresolved reference: foobar
// ACTION: Create function 'foobar'
// ACTION: Rename reference
//KT-9009
fun f() {
foobar<caret>()
}
@@ -367,15 +367,19 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
@TestMetadata("noStaticImportForJavaNonStaticField.test")
public void testNoStaticImportForJavaNonStaticField() throws Exception {
String fileName =
KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/noStaticImportForJavaNonStaticField.test");
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/noStaticImportForJavaNonStaticField.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("noStaticImportForJavaNonStaticMethod.test")
public void testNoStaticImportForJavaNonStaticMethod() throws Exception {
String fileName =
KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/noStaticImportForJavaNonStaticMethod.test");
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/noStaticImportForJavaNonStaticMethod.test");
doTestWithExtraFile(fileName);
}
@TestMetadata("noStaticImportForTopLevelFunction.test")
public void testNoStaticImportForTopLevelFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/autoImports/noStaticImportForTopLevelFunction.test");
doTestWithExtraFile(fileName);
}