Fixed KT-6075 Qualified name inserted when completing class with class object

#KT-6075 Fixed
This commit is contained in:
Valentin Kipyatkov
2014-10-20 20:23:40 +04:00
parent 3a2a7427e7
commit d8dbc46867
5 changed files with 40 additions and 24 deletions
@@ -25,20 +25,15 @@ import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper;
import org.jetbrains.jet.renderer.DescriptorRenderer; import org.jetbrains.jet.renderer.DescriptorRenderer;
import java.util.HashSet; import java.util.HashSet;
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import java.util.ArrayList
import com.intellij.openapi.util.TextRange import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiDocumentManager
import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
import org.jetbrains.jet.renderer.DescriptorRenderer.FQ_NAMES_IN_TYPES
import org.jetbrains.jet.lang.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.jet.lang.resolve.DescriptorUtils import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.resolve.ImportPath
import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector
import java.util.Collections import java.util.Collections
import org.jetbrains.jet.analyzer.analyzeInContext import org.jetbrains.jet.analyzer.analyzeInContext
import org.jetbrains.jet.lang.resolve.calls.callUtil.getCalleeExpressionIfAny import org.jetbrains.jet.lang.resolve.calls.callUtil.getCalleeExpressionIfAny
import java.util.LinkedHashSet import java.util.LinkedHashSet
import org.jetbrains.jet.lang.resolve.ImportPath
public object ShortenReferences { public object ShortenReferences {
public fun process(element: JetElement) { public fun process(element: JetElement) {
@@ -169,10 +164,7 @@ public object ShortenReferences {
val name = target.getName() val name = target.getName()
val targetByName = scope.getClassifier(name) val targetByName = scope.getClassifier(name)
if (targetByName == null) { if (targetByName == null) {
if (target.getContainingDeclaration() is ClassDescriptor) return false return importInserter.addImport(target)
importInserter.addImport(target)
return true
} }
else if (target.asString() == targetByName.asString()) { else if (target.asString() == targetByName.asString()) {
return true return true
@@ -237,8 +229,6 @@ public object ShortenReferences {
val selector = qualifiedExpression.getSelectorExpression() ?: return false val selector = qualifiedExpression.getSelectorExpression() ?: return false
val callee = selector.getCalleeExpressionIfAny() as? JetReferenceExpression ?: return false val callee = selector.getCalleeExpressionIfAny() as? JetReferenceExpression ?: return false
val targetBefore = callee.getTargets(context).singleOrNull() ?: return false val targetBefore = callee.getTargets(context).singleOrNull() ?: return false
val isClassMember = targetBefore.getContainingDeclaration() is ClassDescriptor
val isClassOrPackage = targetBefore is ClassDescriptor || targetBefore is PackageViewDescriptor
val scope = context[BindingContext.RESOLUTION_SCOPE, qualifiedExpression] ?: return false val scope = context[BindingContext.RESOLUTION_SCOPE, qualifiedExpression] ?: return false
val selectorCopy = selector.copy() as JetReferenceExpression val selectorCopy = selector.copy() as JetReferenceExpression
@@ -246,17 +236,9 @@ public object ShortenReferences {
val targetsAfter = (selectorCopy.getCalleeExpressionIfAny() as JetReferenceExpression).getTargets(newContext) val targetsAfter = (selectorCopy.getCalleeExpressionIfAny() as JetReferenceExpression).getTargets(newContext)
when (targetsAfter.size) { when (targetsAfter.size) {
0 -> { 0 -> return importInserter.addImport(targetBefore)
if (!isClassMember && isClassOrPackage) {
importInserter.addImport(targetBefore)
return true
}
return false
}
1 -> { 1 -> if (targetBefore == targetsAfter.first()) return true
if (targetBefore == targetsAfter.first()) return true
}
} }
if (importInserter.optimizeImports()) { if (importInserter.optimizeImports()) {
@@ -290,9 +272,18 @@ public object ShortenReferences {
private class ImportInserter(val file: JetFile) { private class ImportInserter(val file: JetFile) {
private var optimizeImports = true private var optimizeImports = true
fun addImport(descriptor: DeclarationDescriptor) { fun addImport(target: DeclarationDescriptor): Boolean {
val realTarget = if (DescriptorUtils.isClassObject(target)) // references to class object are treated as ones to its owner class
target.getContainingDeclaration() as? ClassDescriptor ?: return false
else
target
if (realTarget !is ClassDescriptor && realTarget !is PackageViewDescriptor) return false
if (realTarget.getContainingDeclaration() is ClassDescriptor) return false // do not insert imports for nested classes
optimizeImports() optimizeImports()
ImportInsertHelper.getInstance().writeImportToFile(ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false), file) ImportInsertHelper.getInstance().writeImportToFile(ImportPath(DescriptorUtils.getFqNameSafe(realTarget), false), file)
return true
} }
fun optimizeImports(): Boolean { fun optimizeImports(): Boolean {
@@ -0,0 +1,5 @@
fun foo() {
KtCla<caret>
}
// ELEMENT: KtClass
@@ -0,0 +1,9 @@
package pack
class KtClass {
fun foo(){}
class object {
fun staticFoo(){}
}
}
@@ -0,0 +1,7 @@
import pack.KtClass
fun foo() {
KtClass<caret>
}
// ELEMENT: KtClass
@@ -62,6 +62,10 @@ public class CompletionMultifileHandlerTest extends KotlinCompletionTestCase {
doTest(); doTest();
} }
public void testClassWithClassObject() throws Exception {
doTest();
}
public void doTest() throws Exception { public void doTest() throws Exception {
String fileName = getTestName(false); String fileName = getTestName(false);