moved more find usages-related stuff to idea-analysis for upsource

This commit is contained in:
Alexey Kudravtsev
2014-10-15 15:11:49 +04:00
parent fff8bfff5f
commit 6f5a2172ac
42 changed files with 566 additions and 320 deletions
@@ -102,4 +102,4 @@ object JetFileReferencesResolver {
}
fun JetExpression.referenceExpression(): JetReferenceExpression? =
(if (this is JetCallExpression) getCalleeExpression() else this) as? JetReferenceExpression
(if (this is JetCallExpression) getCalleeExpression() else this) as? JetReferenceExpression
@@ -99,7 +99,7 @@ public object ShortenReferences {
private fun process(elements: Iterable<JetElement>, elementFilter: (PsiElement) -> FilterResult) {
for ((file, fileElements) in elements.groupBy { element -> element.getContainingJetFile() }) {
ImportInsertHelper.optimizeImportsOnTheFly(file)
ImportInsertHelper.getInstance().optimizeImportsOnTheFly(file)
// first resolve all qualified references - optimization
val referenceToContext = JetFileReferencesResolver.resolve(file, fileElements, resolveShortNames = false)
@@ -335,6 +335,6 @@ public object ShortenReferences {
= "${getExtensionReceiver()}, ${getDispatchReceiver()} -> ${getResultingDescriptor()?.let {FQ_NAMES_IN_TYPES.render(it)}}"
private fun addImport(descriptor: DeclarationDescriptor, file: JetFile) {
ImportInsertHelper.writeImportToFile(ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false), file)
ImportInsertHelper.getInstance().writeImportToFile(ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false), file)
}
}
@@ -0,0 +1,72 @@
/*
* Copyright 2010-2014 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.jet.plugin.codeInsight.shorten
import com.intellij.openapi.project.Project
import com.intellij.psi.SmartPsiElementPointer
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.psi.UserDataProperty
import com.intellij.openapi.util.Key
import org.jetbrains.jet.lang.psi.NotNullableUserDataProperty
import java.util.HashSet
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.SmartPointerManager
import com.intellij.openapi.diagnostic.Logger
private var Project.elementsToShorten: MutableSet<SmartPsiElementPointer<JetElement>>?
by UserDataProperty(Key.create("ELEMENTS_TO_SHORTEN_KEY"))
/*
* When one refactoring invokes another this value must be set to false so that shortening wait-set is not cleared
* and previously collected references are processed correctly. Afterwards it must be reset to original value
*/
public var Project.ensureElementsToShortenIsEmptyBeforeRefactoring: Boolean
by NotNullableUserDataProperty(Key.create("ENSURE_ELEMENTS_TO_SHORTEN_IS_EMPTY"), true)
private fun Project.getOrCreateElementsToShorten(): MutableSet<SmartPsiElementPointer<JetElement>> {
var elements = elementsToShorten
if (elements == null) {
elements = HashSet()
elementsToShorten = elements
}
return elements!!
}
public fun JetElement.addToShorteningWaitSet() {
assert (ApplicationManager.getApplication()!!.isWriteAccessAllowed(), "Write access needed")
val project = getProject()
project.getOrCreateElementsToShorten().add(SmartPointerManager.getInstance(project).createSmartPsiElementPointer(this))
}
public fun withElementsToShorten(project: Project, f: (Set<SmartPsiElementPointer<JetElement>>) -> Unit) {
project.elementsToShorten?.let { bindRequests ->
project.elementsToShorten = null
f(bindRequests)
}
}
private val LOG = Logger.getInstance(javaClass<Project>().getCanonicalName())
public fun prepareElementsToShorten(project: Project) {
val elementsToShorten = project.elementsToShorten
if (project.ensureElementsToShortenIsEmptyBeforeRefactoring && elementsToShorten != null && !elementsToShorten.isEmpty()) {
LOG.warn("Waiting set for reference shortening is not empty")
project.elementsToShorten = null
}
}
@@ -0,0 +1,282 @@
/*
* Copyright 2010-2014 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.jet.plugin.findUsages
import com.intellij.psi.PsiElement
import org.jetbrains.jet.lang.psi.JetForExpression
import org.jetbrains.jet.lang.psi.JetMultiDeclaration
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
import org.jetbrains.jet.lang.psi.JetReferenceExpression
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.psi.JetImportDirective
import org.jetbrains.jet.lang.psi.psiUtil.getParentByTypeAndBranch
import org.jetbrains.jet.lang.psi.JetCallableReferenceExpression
import org.jetbrains.jet.lang.psi.JetProperty
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
import org.jetbrains.jet.lang.psi.JetFunction
import org.jetbrains.jet.lang.psi.JetTypeParameter
import org.jetbrains.jet.lang.psi.JetTypeConstraint
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier
import org.jetbrains.jet.lang.psi.JetTypedef
import org.jetbrains.jet.lang.psi.JetTypeProjection
import org.jetbrains.jet.lang.psi.JetParameter
import org.jetbrains.jet.lang.psi.JetIsExpression
import org.jetbrains.jet.lang.psi.JetBinaryExpressionWithTypeRHS
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.lang.psi.JetDotQualifiedExpression
import org.jetbrains.jet.lang.psi.JetSuperExpression
import org.jetbrains.jet.lang.psi.JetDelegatorByExpressionSpecifier
import org.jetbrains.jet.lang.psi.psiUtil.getParentByTypesAndPredicate
import org.jetbrains.jet.lang.psi.JetBinaryExpression
import org.jetbrains.jet.lang.psi.JetPsiUtil
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
import org.jetbrains.jet.plugin.references.JetArrayAccessReference
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.references.JetInvokeFunctionReference
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor
import org.jetbrains.jet.lang.psi.JetAnnotationEntry
import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.lang.psi.JetUnaryExpression
import org.jetbrains.jet.lang.psi.JetWhenConditionInRange
import org.jetbrains.jet.lang.psi.JetPackageDirective
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
import org.jetbrains.jet.lang.descriptors.ClassKind
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor
import com.intellij.psi.PsiPackage
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
import org.jetbrains.jet.plugin.JetBundle
import org.jetbrains.jet.plugin.findUsages.UsageTypeEnum.*
public object UsageTypeUtils {
public fun getUsageType(element: PsiElement?): UsageTypeEnum? {
when (element) {
is JetForExpression -> return IMPLICIT_ITERATION
is JetMultiDeclaration -> return READ
}
val refExpr = element?.getParentByType(javaClass<JetReferenceExpression>())
if (refExpr == null) return null
val context = AnalyzerFacadeWithCache.getContextForElement(refExpr)
fun getCommonUsageType(): UsageTypeEnum? {
return when {
refExpr.getParentByType(javaClass<JetImportDirective>()) != null ->
CLASS_IMPORT
refExpr.getParentByTypeAndBranch(javaClass<JetCallableReferenceExpression>()) { getCallableReference() } != null ->
CALLABLE_REFERENCE
else -> null
}
}
fun getClassUsageType(): UsageTypeEnum? {
val property = refExpr.getParentByType(javaClass<JetProperty>())
if (property != null) {
when {
property.getTypeReference().isAncestor(refExpr) ->
return if (property.isLocal()) CLASS_LOCAL_VAR_DECLARATION else NON_LOCAL_PROPERTY_TYPE
property.getReceiverTypeReference().isAncestor(refExpr) ->
return EXTENSION_RECEIVER_TYPE
}
}
val function = refExpr.getParentByType(javaClass<JetFunction>())
if (function != null) {
when {
function.getTypeReference().isAncestor(refExpr) ->
return FUNCTION_RETURN_TYPE
function.getReceiverTypeReference().isAncestor(refExpr) ->
return EXTENSION_RECEIVER_TYPE
}
}
return when {
refExpr.getParentByTypeAndBranch(javaClass<JetTypeParameter>()) { getExtendsBound() } != null
|| refExpr.getParentByTypeAndBranch(javaClass<JetTypeConstraint>()) { getBoundTypeReference() } != null ->
TYPE_CONSTRAINT
refExpr is JetDelegationSpecifier
|| refExpr.getParentByTypeAndBranch(javaClass<JetDelegationSpecifier>()) { getTypeReference() } != null ->
SUPER_TYPE
refExpr.getParentByTypeAndBranch(javaClass<JetTypedef>()) { getTypeReference() } != null ->
TYPE_DEFINITION
refExpr.getParentByType(javaClass<JetTypeProjection>()) != null ->
TYPE_PARAMETER
refExpr.getParentByTypeAndBranch(javaClass<JetParameter>()) { getTypeReference() } != null ->
VALUE_PARAMETER_TYPE
refExpr.getParentByTypeAndBranch(javaClass<JetIsExpression>()) { getTypeReference() } != null ->
IS
with(refExpr.getParentByTypeAndBranch(javaClass<JetBinaryExpressionWithTypeRHS>()) { getRight() }) {
val opType = this?.getOperationReference()?.getReferencedNameElementType()
opType == JetTokens.AS_KEYWORD || opType == JetTokens.AS_SAFE
} ->
CLASS_CAST_TO
with(refExpr.getParentByType(javaClass<JetDotQualifiedExpression>())) {
if (this == null) false
else if (getReceiverExpression() == refExpr) true
else
getSelectorExpression() == refExpr
&& getParentByTypeAndBranch(javaClass<JetDotQualifiedExpression>(), true) { getReceiverExpression() } != null
} ->
CLASS_OBJECT_ACCESS
refExpr.getParentByTypeAndBranch(javaClass<JetSuperExpression>()) { getSuperTypeQualifier() } != null ->
SUPER_TYPE_QUALIFIER
else -> null
}
}
fun getVariableUsageType(): UsageTypeEnum? {
if (refExpr.getParentByTypeAndBranch(javaClass<JetDelegatorByExpressionSpecifier>()) { getDelegateExpression() } != null) {
return DELEGATE
}
val dotQualifiedExpression = refExpr.getParentByType(javaClass<JetDotQualifiedExpression>())
if (dotQualifiedExpression != null) {
val parent = dotQualifiedExpression.getParent()
when {
dotQualifiedExpression.getReceiverExpression().isAncestor(refExpr) ->
return RECEIVER
parent is JetDotQualifiedExpression && parent.getReceiverExpression().isAncestor(refExpr) ->
return RECEIVER
}
}
return when {
(refExpr.getParentByTypesAndPredicate(false, javaClass<JetBinaryExpression>()) { JetPsiUtil.isAssignment(it) })
?.getLeft().isAncestor(refExpr) ->
WRITE
refExpr.getParentByType(javaClass<JetSimpleNameExpression>()) != null ->
READ
else -> null
}
}
fun getFunctionUsageType(descriptor: FunctionDescriptor): UsageTypeEnum? {
val ref = refExpr.getReference()
when (ref) {
is JetArrayAccessReference -> {
return when {
context[BindingContext.INDEXED_LVALUE_GET, refExpr] != null -> IMPLICIT_GET
context[BindingContext.INDEXED_LVALUE_SET, refExpr] != null -> IMPLICIT_SET
else -> null
}
}
is JetInvokeFunctionReference -> return IMPLICIT_INVOKE
}
return when {
refExpr.getParentByTypeAndBranch(javaClass<JetDelegationSpecifier>()) { getTypeReference() } != null ->
SUPER_TYPE
descriptor is ConstructorDescriptor
&& refExpr.getParentByTypeAndBranch(javaClass<JetAnnotationEntry>()) { getTypeReference() } != null ->
ANNOTATION
with(refExpr.getParentByTypeAndBranch(javaClass<JetCallExpression>()) { getCalleeExpression() }) {
this?.getCalleeExpression() is JetSimpleNameExpression
} ->
if (descriptor is ConstructorDescriptor) CLASS_NEW_OPERATOR else FUNCTION_CALL
refExpr.getParentByTypeAndBranch(javaClass<JetBinaryExpression>()) { getOperationReference() } != null,
refExpr.getParentByTypeAndBranch(javaClass<JetUnaryExpression>()) { getOperationReference() } != null,
refExpr.getParentByTypeAndBranch(javaClass<JetWhenConditionInRange>()) { getOperationReference() } != null ->
FUNCTION_CALL
else -> null
}
}
fun getPackageUsageType(): UsageTypeEnum? {
return when {
refExpr.getParentByType(javaClass<JetPackageDirective>()) != null -> PACKAGE_DIRECTIVE
refExpr.getParentByType(javaClass<JetQualifiedExpression>()) != null -> PACKAGE_MEMBER_ACCESS
else -> getClassUsageType()
}
}
val usageType = getCommonUsageType()
if (usageType != null) return usageType
val descriptor = context[BindingContext.REFERENCE_TARGET, refExpr]
return when (descriptor) {
is ClassifierDescriptor -> when ((descriptor as? ClassDescriptor)?.getKind()) {
// Treat object accesses as variables to simulate the old behaviour (when variables were created for objects)
ClassKind.OBJECT, ClassKind.ENUM_ENTRY -> getVariableUsageType()
else -> getClassUsageType()
}
is PackageViewDescriptor -> {
if (refExpr.getReference()?.resolve() is PsiPackage) getPackageUsageType() else getClassUsageType()
}
is VariableDescriptor -> getVariableUsageType()
is FunctionDescriptor -> getFunctionUsageType(descriptor)
else -> null
}
}
}
enum class UsageTypeEnum {
TYPE_CONSTRAINT
VALUE_PARAMETER_TYPE
NON_LOCAL_PROPERTY_TYPE
FUNCTION_RETURN_TYPE
SUPER_TYPE
TYPE_DEFINITION
IS
CLASS_OBJECT_ACCESS
EXTENSION_RECEIVER_TYPE
SUPER_TYPE_QUALIFIER
FUNCTION_CALL
IMPLICIT_GET
IMPLICIT_SET
IMPLICIT_INVOKE
IMPLICIT_ITERATION
RECEIVER
DELEGATE
PACKAGE_DIRECTIVE
PACKAGE_MEMBER_ACCESS
CALLABLE_REFERENCE
READ
WRITE
CLASS_IMPORT
CLASS_LOCAL_VAR_DECLARATION
TYPE_PARAMETER
CLASS_CAST_TO
ANNOTATION
CLASS_NEW_OPERATOR
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2014 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.jet.plugin.quickfix;
import com.intellij.openapi.components.ServiceManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetImportDirective;
import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.name.FqName;
import java.util.List;
public abstract class ImportInsertHelper {
public static ImportInsertHelper getInstance() {
return ServiceManager.getService(ImportInsertHelper.class);
}
public abstract void addImportDirectiveIfNeeded(@NotNull FqName importFqn, @NotNull JetFile file);
public abstract boolean isImportedWithDefault(@NotNull ImportPath importPath, @NotNull JetFile contextFile);
public abstract boolean needImport(@NotNull FqName fqName, @NotNull JetFile file);
public abstract boolean needImport(@NotNull ImportPath importPath, @NotNull JetFile file);
public abstract boolean needImport(@NotNull ImportPath importPath, @NotNull JetFile file, List<JetImportDirective> importDirectives);
public abstract void optimizeImportsOnTheFly(JetFile file);
public abstract void writeImportToFile(@NotNull ImportPath importPath, @NotNull JetFile file);
}
@@ -0,0 +1,76 @@
/*
* Copyright 2010-2014 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.jet.plugin.refactoring.fqName
import org.jetbrains.jet.asJava.namedUnwrappedElement
import com.intellij.psi.PsiElement
import org.jetbrains.jet.lang.resolve.name.FqName
import com.intellij.psi.PsiPackage
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiMember
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
import org.jetbrains.jet.lang.resolve.name.isOneSegmentFQN
import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElement
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.psi.JetCallExpression
import org.jetbrains.jet.lang.psi.JetUserType
import org.jetbrains.jet.lang.psi
/**
* Returns FqName for given declaration (either Java or Kotlin)
*/
public fun PsiElement.getKotlinFqName(): FqName? {
val element = namedUnwrappedElement
return when (element) {
is PsiPackage -> FqName(element.getQualifiedName())
is PsiClass -> element.getQualifiedName()?.let { FqName(it) }
is PsiMember -> (element : PsiMember).getName()?.let { name ->
val prefix = element.getContainingClass()?.getQualifiedName()
FqName(if (prefix != null) "$prefix.$name" else name)
}
is JetNamedDeclaration -> element.getFqName()
else -> null
}
}
/**
* Replace [[JetSimpleNameExpression]] (and its enclosing qualifier) with qualified element given by FqName
* Result is either the same as original element, or [[JetQualifiedExpression]], or [[JetUserType]]
* Note that FqName may not be empty
*/
fun JetSimpleNameExpression.changeQualifiedName(fqName: FqName): JetElement {
assert (!fqName.isRoot(), "Can't set empty FqName for element $this")
val shortName = fqName.shortName().asString()
val psiFactory = psi.JetPsiFactory(this)
val fqNameBase = (getParent() as? JetCallExpression)?.let { parent ->
val callCopy = parent.copy() as JetCallExpression
callCopy.getCalleeExpression()!!.replace(psiFactory.createSimpleName(shortName)).getParent()!!.getText()
} ?: shortName
val text = if (!fqName.isOneSegmentFQN()) "${fqName.parent().asString()}.$fqNameBase" else fqNameBase
val elementToReplace = getQualifiedElement()
return when (elementToReplace) {
is JetUserType -> {
val typeText = "$text${elementToReplace.getTypeArgumentList()?.getText() ?: ""}"
elementToReplace.replace(psiFactory.createType(typeText).getTypeElement()!!)
}
else -> elementToReplace.replace(psiFactory.createExpression(text))
} as JetElement
}
@@ -59,4 +59,4 @@ public class JetReferenceContributor() : PsiReferenceContributor() {
}
})
}
}
}
@@ -23,11 +23,11 @@ import org.jetbrains.jet.lang.psi.*
import org.jetbrains.jet.lang.resolve.name.FqName
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.plugin.codeInsight.ShortenReferences
import org.jetbrains.jet.plugin.refactoring.changeQualifiedName
import org.jetbrains.jet.plugin.refactoring.fqName.changeQualifiedName
import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector
import org.jetbrains.jet.lang.psi.psiUtil.getOutermostNonInterleavingQualifiedElement
import org.jetbrains.jet.plugin.codeInsight.addToShorteningWaitSet
import org.jetbrains.jet.plugin.refactoring.getKotlinFqName
import org.jetbrains.jet.plugin.codeInsight.shorten.addToShorteningWaitSet
import org.jetbrains.jet.plugin.refactoring.fqName.getKotlinFqName
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
import org.jetbrains.jet.lexer.JetToken
import org.jetbrains.jet.plugin.intentions.OperatorToFunctionIntention
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
* Copyright 2010-2014 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.
@@ -30,7 +30,6 @@ import com.intellij.psi.search.searches.ReferenceDescriptor
import com.intellij.util.containers.ContainerUtil
import com.intellij.psi.search.UsageSearchContext
import com.intellij.psi.PsiElement
import com.intellij.psi.search.RequestResultProcessor
import com.intellij.util.Processor
import com.intellij.openapi.application.QueryExecutorBase
import com.intellij.psi.PsiReferenceService
@@ -49,7 +48,6 @@ import com.intellij.util.indexing.FileBasedIndex
import com.intellij.psi.impl.cache.impl.id.IdIndex
import org.jetbrains.jet.plugin.util.application.runReadAction
import com.intellij.psi.search.TextOccurenceProcessor
import org.jetbrains.jet.plugin.references.JetMultiDeclarationReference
import com.intellij.psi.PsiManager
import com.intellij.psi.impl.PsiManagerEx
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
* Copyright 2010-2014 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.
@@ -24,13 +24,13 @@ import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import com.intellij.psi.PsiReference
import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.plugin.findUsages.JetUsageTypeProvider
import com.intellij.usages.impl.rules.UsageType
import org.jetbrains.jet.codegen.PropertyCodegen
import org.jetbrains.jet.asJava.KotlinLightMethod
import org.jetbrains.jet.lang.resolve.OverrideResolver
import org.jetbrains.jet.lang.resolve.DescriptorToSourceUtils
import org.jetbrains.jet.plugin.references.*
import org.jetbrains.jet.plugin.findUsages.UsageTypeUtils
import org.jetbrains.jet.plugin.findUsages.UsageTypeEnum
val JetDeclaration.descriptor: DeclarationDescriptor?
get() = AnalyzerFacadeWithCache.getContextForElement(this).get(BindingContext.DECLARATION_TO_DESCRIPTOR, this)
@@ -106,7 +106,7 @@ fun PsiReference.isExtensionOfDeclarationClassUsage(declaration: JetNamedDeclara
val containingDescriptor = targetDescriptor.getContainingDeclaration()
containingDescriptor == receiverDescriptor
|| (containingDescriptor is ClassDescriptor
|| (containingDescriptor is ClassDescriptor
&& receiverDescriptor is ClassDescriptor
&& DescriptorUtils.isSubclass(containingDescriptor, receiverDescriptor))
}
@@ -118,7 +118,7 @@ fun PsiReference.isExtensionOfDeclarationClassUsage(declaration: JetNamedDeclara
fun PsiReference.isUsageInContainingDeclaration(declaration: JetNamedDeclaration): Boolean =
checkUsageVsOriginalDescriptor(declaration) { (usageDescriptor, targetDescriptor) ->
usageDescriptor != targetDescriptor
&& usageDescriptor.getContainingDeclaration() == targetDescriptor.getContainingDeclaration()
&& usageDescriptor.getContainingDeclaration() == targetDescriptor.getContainingDeclaration()
}
fun PsiReference.isCallableOverrideUsage(declaration: JetNamedDeclaration): Boolean {
@@ -128,7 +128,7 @@ fun PsiReference.isCallableOverrideUsage(declaration: JetNamedDeclaration): Bool
return checkUsageVsOriginalDescriptor(declaration, decl2Desc) { (usageDescriptor, targetDescriptor) ->
usageDescriptor is CallableDescriptor && targetDescriptor is CallableDescriptor
&& OverrideResolver.overrides(usageDescriptor, targetDescriptor)
&& OverrideResolver.overrides(usageDescriptor, targetDescriptor)
}
}
@@ -136,7 +136,7 @@ fun PsiReference.isCallableOverrideUsage(declaration: JetNamedDeclaration): Bool
// Check if reference resolves to property getter
// Works for JetProperty and JetParameter
fun PsiReference.isPropertyReadOnlyUsage(): Boolean {
if (JetUsageTypeProvider.getUsageType(getElement()) == UsageType.READ) return true
if (UsageTypeUtils.getUsageType(getElement()) == UsageTypeEnum.READ) return true
val refTarget = resolve()
if (refTarget is KotlinLightMethod) {
+2
View File
@@ -131,6 +131,8 @@
<applicationService serviceInterface="org.jetbrains.jet.plugin.configuration.JetModuleTypeManager"
serviceImplementation="org.jetbrains.jet.plugin.JetModuleTypeManagerImpl"/>
<applicationService serviceInterface="org.jetbrains.jet.plugin.quickfix.ImportInsertHelper"
serviceImplementation="org.jetbrains.jet.plugin.quickfix.ImportInsertHelperImpl"/>
<projectService serviceInterface="org.jetbrains.jet.plugin.caches.resolve.KotlinCacheService"
serviceImplementation="org.jetbrains.jet.plugin.caches.resolve.KotlinCacheService"/>
@@ -157,7 +157,7 @@ public class JetAddImportAction implements QuestionAction {
public void run() {
PsiFile file = element.getContainingFile();
if (!(file instanceof JetFile)) return;
ImportInsertHelper.addImportDirectiveIfNeeded(selectedImport, (JetFile) file);
ImportInsertHelper.getInstance().addImportDirectiveIfNeeded(selectedImport, (JetFile) file);
}
});
}
@@ -223,7 +223,7 @@ public class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<Refere
return Collections.emptyList()
}
return referenceData.map {
if (ImportInsertHelper.needImport(it.fqName, file)) {
if (ImportInsertHelper.getInstance().needImport(it.fqName, file)) {
val referenceExpression = findReference(it, file, bounds)
if (referenceExpression != null) createReferenceToRestoreData(referenceExpression, it.fqName) else null
}
@@ -287,7 +287,7 @@ public class KotlinCopyPasteReferenceProcessor() : CopyPastePostProcessor<Refere
private fun restoreReferences(referencesToRestore: Collection<ReferenceToRestoreData>, file: JetFile) {
for ((referenceExpression, fqName, shouldLengthen) in referencesToRestore) {
if (!shouldLengthen) {
ImportInsertHelper.addImportDirectiveIfNeeded(fqName, file)
ImportInsertHelper.getInstance().addImportDirectiveIfNeeded(fqName, file)
}
else {
//TODO: try to shorten reference after (sometimes is possible), need shorten reference to support all relevant cases
@@ -19,67 +19,24 @@ package org.jetbrains.jet.plugin.codeInsight
import com.intellij.refactoring.RefactoringHelper
import com.intellij.usageView.UsageInfo
import com.intellij.openapi.project.Project
import java.util.HashSet
import com.intellij.openapi.util.Key
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.SmartPsiElementPointer
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import com.intellij.openapi.diagnostic.Logger
import com.intellij.psi.SmartPointerManager
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
import org.jetbrains.jet.lang.psi.JetUserType
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.lang.psi.UserDataProperty
import org.jetbrains.jet.lang.psi.NotNullableUserDataProperty
import org.jetbrains.jet.plugin.codeInsight.shorten.prepareElementsToShorten
import org.jetbrains.jet.plugin.codeInsight.shorten.withElementsToShorten
public class KotlinShortenReferencesRefactoringHelper: RefactoringHelper<Any> {
private val LOG = Logger.getInstance(javaClass<KotlinShortenReferencesRefactoringHelper>().getCanonicalName())
override fun prepareOperation(usages: Array<out UsageInfo>?): Any? {
if (usages != null && usages.isNotEmpty()) {
val project = usages[0].getProject()
val elementsToShorten = project.elementsToShorten
if (project.ensureElementsToShortenIsEmptyBeforeRefactoring && elementsToShorten != null && !elementsToShorten.isEmpty()) {
LOG.warn("Waiting set for reference shortening is not empty")
project.elementsToShorten = null
}
prepareElementsToShorten(project)
}
return null
}
override fun performOperation(project: Project, operationData: Any?) {
ApplicationManager.getApplication()!!.runWriteAction {
project.elementsToShorten?.let { bindRequests ->
project.elementsToShorten = null
withElementsToShorten(project) { bindRequests ->
ShortenReferences.process(bindRequests.map() { it.getElement() }.filterNotNull())
}
}
}
}
private var Project.elementsToShorten: MutableSet<SmartPsiElementPointer<JetElement>>?
by UserDataProperty(Key.create("ELEMENTS_TO_SHORTEN_KEY"))
/*
* When one refactoring invokes another this value must be set to false so that shortening wait-set is not cleared
* and previously collected references are processed correctly. Afterwards it must be reset to original value
*/
public var Project.ensureElementsToShortenIsEmptyBeforeRefactoring: Boolean
by NotNullableUserDataProperty(Key.create("ENSURE_ELEMENTS_TO_SHORTEN_IS_EMPTY"), true)
private fun Project.getOrCreateElementsToShorten(): MutableSet<SmartPsiElementPointer<JetElement>> {
var elements = elementsToShorten
if (elements == null) {
elements = HashSet()
elementsToShorten = elements
}
return elements!!
}
public fun JetElement.addToShorteningWaitSet() {
assert (ApplicationManager.getApplication()!!.isWriteAccessAllowed(), "Write access needed")
val project = getProject()
project.getOrCreateElementsToShorten().add(SmartPointerManager.getInstance(project).createSmartPsiElementPointer(this))
}
@@ -126,8 +126,8 @@ private class JetDeclarationRemotenessWeigher(private val file: JetFile) : Looku
if (isValidJavaFqName(fqName)) {
val importPath = ImportPath(fqName)
return when {
ImportInsertHelper.needImport(importPath, file) -> Weight.notImported
ImportInsertHelper.isImportedWithDefault(importPath, file) -> Weight.kotlinDefaultImport
ImportInsertHelper.getInstance().needImport(importPath, file) -> Weight.notImported
ImportInsertHelper.getInstance().isImportedWithDefault(importPath, file) -> Weight.kotlinDefaultImport
else -> Weight.imported
}
}
@@ -67,7 +67,7 @@ public abstract class JetCallableInsertHandler : BaseDeclarationInsertHandler()
if (DescriptorUtils.isTopLevelDeclaration(descriptor)) {
ApplicationManager.getApplication()?.runWriteAction {
ImportInsertHelper.addImportDirectiveIfNeeded(DescriptorUtils.getFqNameSafe(descriptor), file)
ImportInsertHelper.getInstance().addImportDirectiveIfNeeded(DescriptorUtils.getFqNameSafe(descriptor), file)
}
}
}
@@ -20,16 +20,8 @@ import com.intellij.psi.PsiElement
import com.intellij.usages.UsageTarget
import com.intellij.usages.impl.rules.UsageType
import com.intellij.usages.impl.rules.UsageTypeProviderEx
import org.jetbrains.jet.lang.descriptors.*
import org.jetbrains.jet.lang.psi.*
import org.jetbrains.jet.lang.psi.psiUtil.*
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.plugin.JetBundle
import com.intellij.psi.PsiPackage
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.plugin.references.JetArrayAccessReference
import org.jetbrains.jet.plugin.references.JetInvokeFunctionReference
import org.jetbrains.jet.plugin.findUsages.UsageTypeEnum.*
public object JetUsageTypeProvider : UsageTypeProviderEx {
public override fun getUsageType(element: PsiElement?): UsageType? {
@@ -37,181 +29,46 @@ public object JetUsageTypeProvider : UsageTypeProviderEx {
}
public override fun getUsageType(element: PsiElement?, targets: Array<out UsageTarget>): UsageType? {
when (element) {
is JetForExpression -> return JetUsageTypes.IMPLICIT_ITERATION
is JetMultiDeclaration -> return UsageType.READ
}
val usageType = UsageTypeUtils.getUsageType(element)
if (usageType == null) return null
return convertEnumToUsageType(usageType)
}
val refExpr = element?.getParentByType(javaClass<JetReferenceExpression>())
if (refExpr == null) return null
fun convertEnumToUsageType(usageType: UsageTypeEnum): UsageType {
return when (usageType) {
TYPE_CONSTRAINT -> JetUsageTypes.TYPE_CONSTRAINT
VALUE_PARAMETER_TYPE -> JetUsageTypes.VALUE_PARAMETER_TYPE
NON_LOCAL_PROPERTY_TYPE -> JetUsageTypes.NON_LOCAL_PROPERTY_TYPE
FUNCTION_RETURN_TYPE -> JetUsageTypes.FUNCTION_RETURN_TYPE
SUPER_TYPE -> JetUsageTypes.SUPER_TYPE
TYPE_DEFINITION -> JetUsageTypes.TYPE_DEFINITION
IS -> JetUsageTypes.IS
CLASS_OBJECT_ACCESS -> JetUsageTypes.CLASS_OBJECT_ACCESS
EXTENSION_RECEIVER_TYPE -> JetUsageTypes.EXTENSION_RECEIVER_TYPE
SUPER_TYPE_QUALIFIER -> JetUsageTypes.SUPER_TYPE_QUALIFIER
val context = AnalyzerFacadeWithCache.getContextForElement(refExpr)
FUNCTION_CALL -> JetUsageTypes.FUNCTION_CALL
IMPLICIT_GET -> JetUsageTypes.IMPLICIT_GET
IMPLICIT_SET -> JetUsageTypes.IMPLICIT_SET
IMPLICIT_INVOKE -> JetUsageTypes.IMPLICIT_INVOKE
IMPLICIT_ITERATION -> JetUsageTypes.IMPLICIT_ITERATION
fun getCommonUsageType(): UsageType? {
return when {
refExpr.getParentByType(javaClass<JetImportDirective>()) != null ->
UsageType.CLASS_IMPORT
refExpr.getParentByTypeAndBranch(javaClass<JetCallableReferenceExpression>()) { getCallableReference() } != null ->
JetUsageTypes.CALLABLE_REFERENCE
else -> null
}
}
RECEIVER -> JetUsageTypes.RECEIVER
DELEGATE -> JetUsageTypes.DELEGATE
fun getClassUsageType(): UsageType? {
val property = refExpr.getParentByType(javaClass<JetProperty>())
if (property != null) {
when {
property.getTypeReference().isAncestor(refExpr) ->
return if (property.isLocal()) UsageType.CLASS_LOCAL_VAR_DECLARATION else JetUsageTypes.NON_LOCAL_PROPERTY_TYPE
PACKAGE_DIRECTIVE -> JetUsageTypes.PACKAGE_DIRECTIVE
PACKAGE_MEMBER_ACCESS -> JetUsageTypes.PACKAGE_MEMBER_ACCESS
property.getReceiverTypeReference().isAncestor(refExpr) ->
return JetUsageTypes.EXTENSION_RECEIVER_TYPE
}
}
CALLABLE_REFERENCE -> JetUsageTypes.CALLABLE_REFERENCE
val function = refExpr.getParentByType(javaClass<JetFunction>())
if (function != null) {
when {
function.getTypeReference().isAncestor(refExpr) ->
return JetUsageTypes.FUNCTION_RETURN_TYPE
function.getReceiverTypeReference().isAncestor(refExpr) ->
return JetUsageTypes.EXTENSION_RECEIVER_TYPE
}
}
return when {
refExpr.getParentByTypeAndBranch(javaClass<JetTypeParameter>()) { getExtendsBound() } != null
|| refExpr.getParentByTypeAndBranch(javaClass<JetTypeConstraint>()) { getBoundTypeReference() } != null ->
JetUsageTypes.TYPE_CONSTRAINT
refExpr is JetDelegationSpecifier
|| refExpr.getParentByTypeAndBranch(javaClass<JetDelegationSpecifier>()) { getTypeReference() } != null ->
JetUsageTypes.SUPER_TYPE
refExpr.getParentByTypeAndBranch(javaClass<JetTypedef>()) { getTypeReference() } != null ->
JetUsageTypes.TYPE_DEFINITION
refExpr.getParentByType(javaClass<JetTypeProjection>()) != null ->
UsageType.TYPE_PARAMETER
refExpr.getParentByTypeAndBranch(javaClass<JetParameter>()) { getTypeReference() } != null ->
JetUsageTypes.VALUE_PARAMETER_TYPE
refExpr.getParentByTypeAndBranch(javaClass<JetIsExpression>()) { getTypeReference() } != null ->
JetUsageTypes.IS
with(refExpr.getParentByTypeAndBranch(javaClass<JetBinaryExpressionWithTypeRHS>()) { getRight() }) {
val opType = this?.getOperationReference()?.getReferencedNameElementType()
opType == JetTokens.AS_KEYWORD || opType == JetTokens.AS_SAFE
} ->
UsageType.CLASS_CAST_TO
with(refExpr.getParentByType(javaClass<JetDotQualifiedExpression>())) {
if (this == null) false
else if (getReceiverExpression() == refExpr) true
else
getSelectorExpression() == refExpr
&& getParentByTypeAndBranch(javaClass<JetDotQualifiedExpression>(), true) { getReceiverExpression() } != null
} ->
JetUsageTypes.CLASS_OBJECT_ACCESS
refExpr.getParentByTypeAndBranch(javaClass<JetSuperExpression>()) { getSuperTypeQualifier() } != null ->
JetUsageTypes.SUPER_TYPE_QUALIFIER
else -> null
}
}
fun getVariableUsageType(): UsageType? {
if (refExpr.getParentByTypeAndBranch(javaClass<JetDelegatorByExpressionSpecifier>()) { getDelegateExpression() } != null) {
return JetUsageTypes.DELEGATE
}
val dotQualifiedExpression = refExpr.getParentByType(javaClass<JetDotQualifiedExpression>())
if (dotQualifiedExpression != null) {
val parent = dotQualifiedExpression.getParent()
when {
dotQualifiedExpression.getReceiverExpression().isAncestor(refExpr) ->
return JetUsageTypes.RECEIVER
parent is JetDotQualifiedExpression && parent.getReceiverExpression().isAncestor(refExpr) ->
return JetUsageTypes.RECEIVER
}
}
return when {
(refExpr.getParentByTypesAndPredicate(false, javaClass<JetBinaryExpression>()) { JetPsiUtil.isAssignment(it) })
?.getLeft().isAncestor(refExpr) ->
UsageType.WRITE
refExpr.getParentByType(javaClass<JetSimpleNameExpression>()) != null ->
UsageType.READ
else -> null
}
}
fun getFunctionUsageType(descriptor: FunctionDescriptor): UsageType? {
val ref = refExpr.getReference()
when (ref) {
is JetArrayAccessReference -> {
return when {
context[BindingContext.INDEXED_LVALUE_GET, refExpr] != null -> JetUsageTypes.IMPLICIT_GET
context[BindingContext.INDEXED_LVALUE_SET, refExpr] != null -> JetUsageTypes.IMPLICIT_SET
else -> null
}
}
is JetInvokeFunctionReference -> return JetUsageTypes.IMPLICIT_INVOKE
}
return when {
refExpr.getParentByTypeAndBranch(javaClass<JetDelegationSpecifier>()) { getTypeReference() } != null ->
JetUsageTypes.SUPER_TYPE
descriptor is ConstructorDescriptor
&& refExpr.getParentByTypeAndBranch(javaClass<JetAnnotationEntry>()) { getTypeReference() } != null ->
UsageType.ANNOTATION
with(refExpr.getParentByTypeAndBranch(javaClass<JetCallExpression>()) { getCalleeExpression() }) {
this?.getCalleeExpression() is JetSimpleNameExpression
} ->
if (descriptor is ConstructorDescriptor) UsageType.CLASS_NEW_OPERATOR else JetUsageTypes.FUNCTION_CALL
refExpr.getParentByTypeAndBranch(javaClass<JetBinaryExpression>()) { getOperationReference() } != null,
refExpr.getParentByTypeAndBranch(javaClass<JetUnaryExpression>()) { getOperationReference() } != null,
refExpr.getParentByTypeAndBranch(javaClass<JetWhenConditionInRange>()) { getOperationReference() } != null ->
JetUsageTypes.FUNCTION_CALL
else -> null
}
}
fun getPackageUsageType(): UsageType? {
return when {
refExpr.getParentByType(javaClass<JetPackageDirective>()) != null -> JetUsageTypes.PACKAGE_DIRECTIVE
refExpr.getParentByType(javaClass<JetQualifiedExpression>()) != null -> JetUsageTypes.PACKAGE_MEMBER_ACCESS
else -> getClassUsageType()
}
}
val usageType = getCommonUsageType()
if (usageType != null) return usageType
val descriptor = context[BindingContext.REFERENCE_TARGET, refExpr]
return when (descriptor) {
is ClassifierDescriptor -> when ((descriptor as? ClassDescriptor)?.getKind()) {
// Treat object accesses as variables to simulate the old behaviour (when variables were created for objects)
ClassKind.OBJECT, ClassKind.ENUM_ENTRY -> getVariableUsageType()
else -> getClassUsageType()
}
is PackageViewDescriptor -> {
if (refExpr.getReference()?.resolve() is PsiPackage) getPackageUsageType() else getClassUsageType()
}
is VariableDescriptor -> getVariableUsageType()
is FunctionDescriptor -> getFunctionUsageType(descriptor)
else -> null
READ -> UsageType.READ
WRITE -> UsageType.WRITE
CLASS_IMPORT -> UsageType.CLASS_IMPORT
CLASS_LOCAL_VAR_DECLARATION -> UsageType.CLASS_LOCAL_VAR_DECLARATION
TYPE_PARAMETER -> UsageType.TYPE_PARAMETER
CLASS_CAST_TO -> UsageType.CLASS_CAST_TO
ANNOTATION -> UsageType.ANNOTATION
CLASS_NEW_OPERATOR -> UsageType.CLASS_NEW_OPERATOR
}
}
}
@@ -27,8 +27,8 @@ import org.jetbrains.jet.lang.resolve.ImportPath
import org.jetbrains.jet.lang.resolve.name.*
import org.jetbrains.jet.plugin.references.JetReference
import java.util.HashSet
import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper.needImport
import java.util.ArrayList
import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper
public class KotlinImportOptimizer() : ImportOptimizer {
@@ -54,8 +54,8 @@ public class KotlinImportOptimizer() : ImportOptimizer {
}
if (isUseful(importPath, usedQualifiedNames)
&& needImport(importPath, jetFile, directivesBeforeCurrent)
&& needImport(importPath, jetFile, directivesAfterCurrent)
&& ImportInsertHelper.getInstance().needImport(importPath, jetFile, directivesBeforeCurrent)
&& ImportInsertHelper.getInstance().needImport(importPath, jetFile, directivesAfterCurrent)
) {
directivesBeforeCurrent.add(anImport)
}
@@ -122,7 +122,7 @@ public class AutoImportFix(element: JetSimpleNameExpression) : JetHintAction<Jet
result.addAll(getExtensions(referenceName, element, searchScope, resolveSession, file.getProject()))
return result
.filter { ImportInsertHelper.needImport(ImportPath(it.fqName, false), file) }
.filter { ImportInsertHelper.getInstance().needImport(ImportPath(it.fqName, false), file) }
.sortBy { it.priority.ordinal() }
.map { it.fqName }
}
@@ -31,17 +31,15 @@ import java.util.List;
import static org.jetbrains.jet.lang.psi.PsiPackage.JetPsiFactory;
public class ImportInsertHelper {
private ImportInsertHelper() {
}
public class ImportInsertHelperImpl extends ImportInsertHelper {
/**
* Add import directive into the PSI tree for the given package.
*
* @param importFqn full name of the import
* @param file File where directive should be added.
*/
public static void addImportDirectiveIfNeeded(@NotNull FqName importFqn, @NotNull JetFile file) {
@Override
public void addImportDirectiveIfNeeded(@NotNull FqName importFqn, @NotNull JetFile file) {
ImportPath importPath = new ImportPath(importFqn, false);
optimizeImportsOnTheFly(file);
@@ -51,13 +49,14 @@ public class ImportInsertHelper {
}
}
public static void optimizeImportsOnTheFly(JetFile file) {
@Override
public void optimizeImportsOnTheFly(JetFile file) {
if (CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) {
new OptimizeImportsProcessor(file.getProject(), file).runWithoutProgress();
}
}
public static void writeImportToFile(@NotNull ImportPath importPath, @NotNull JetFile file) {
public void writeImportToFile(@NotNull ImportPath importPath, @NotNull JetFile file) {
JetPsiFactory psiFactory = JetPsiFactory(file.getProject());
if (file instanceof JetCodeFragment) {
JetImportDirective newDirective = psiFactory.createImportDirective(importPath);
@@ -85,7 +84,7 @@ public class ImportInsertHelper {
/**
* Check that import is useless.
*/
private static boolean isImportedByDefault(@NotNull ImportPath importPath, @NotNull JetFile jetFile) {
private boolean isImportedByDefault(@NotNull ImportPath importPath, @NotNull JetFile jetFile) {
if (importPath.fqnPart().isRoot()) {
return true;
}
@@ -105,22 +104,26 @@ public class ImportInsertHelper {
return isImportedWithDefault(importPath, jetFile);
}
public static boolean isImportedWithDefault(@NotNull ImportPath importPath, @NotNull JetFile contextFile) {
@Override
public boolean isImportedWithDefault(@NotNull ImportPath importPath, @NotNull JetFile contextFile) {
List<ImportPath> defaultImports = ProjectStructureUtil.isJsKotlinModule(contextFile)
? TopDownAnalyzerFacadeForJS.DEFAULT_IMPORTS
: TopDownAnalyzerFacadeForJVM.DEFAULT_IMPORTS;
return NamePackage.isImported(importPath, defaultImports);
}
public static boolean needImport(@NotNull FqName fqName, @NotNull JetFile file) {
@Override
public boolean needImport(@NotNull FqName fqName, @NotNull JetFile file) {
return needImport(new ImportPath(fqName, false), file);
}
public static boolean needImport(@NotNull ImportPath importPath, @NotNull JetFile file) {
@Override
public boolean needImport(@NotNull ImportPath importPath, @NotNull JetFile file) {
return needImport(importPath, file, file.getImportDirectives());
}
public static boolean needImport(@NotNull ImportPath importPath, @NotNull JetFile file, List<JetImportDirective> importDirectives) {
@Override
public boolean needImport(@NotNull ImportPath importPath, @NotNull JetFile file, List<JetImportDirective> importDirectives) {
if (isImportedByDefault(importPath, file)) {
return false;
}
@@ -508,7 +508,7 @@ fun ExtractableCodeDescriptor.generateDeclaration(options: ExtractionGeneratorOp
if (options.inTempFile) return ExtractionResult(declaration, Collections.emptyMap(), nameByOffset)
makeCall(this, declaration, controlFlow, extractionData.originalRange, parameters.map { it.argumentText })
ShortenReferences.process(declaration)
ShortenReferences.process(declaration)
val duplicateReplacers = duplicates.map { it.range to { makeCall(this, declaration, it.controlFlow, it.range, it.arguments) } }.toMap()
return ExtractionResult(declaration, duplicateReplacers, nameByOffset)
@@ -74,33 +74,6 @@ import com.intellij.openapi.util.text.StringUtil
import javax.swing.Icon
import org.jetbrains.jet.plugin.util.string.collapseSpaces
/**
* Replace [[JetSimpleNameExpression]] (and its enclosing qualifier) with qualified element given by FqName
* Result is either the same as original element, or [[JetQualifiedExpression]], or [[JetUserType]]
* Note that FqName may not be empty
*/
fun JetSimpleNameExpression.changeQualifiedName(fqName: FqName): JetElement {
assert (!fqName.isRoot(), "Can't set empty FqName for element $this")
val shortName = fqName.shortName().asString()
val psiFactory = JetPsiFactory(this)
val fqNameBase = (getParent() as? JetCallExpression)?.let { parent ->
val callCopy = parent.copy() as JetCallExpression
callCopy.getCalleeExpression()!!.replace(psiFactory.createSimpleName(shortName)).getParent()!!.getText()
} ?: shortName
val text = if (!fqName.isOneSegmentFQN()) "${fqName.parent().asString()}.$fqNameBase" else fqNameBase
val elementToReplace = getQualifiedElement()
return when (elementToReplace) {
is JetUserType -> {
val typeText = "$text${elementToReplace.getTypeArgumentList()?.getText() ?: ""}"
elementToReplace.replace(psiFactory.createType(typeText).getTypeElement()!!)
}
else -> elementToReplace.replace(psiFactory.createExpression(text))
} as JetElement
}
fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? {
val data = getCopyableUserData(key)
putCopyableUserData(key, null)
@@ -124,23 +97,6 @@ public fun File.toPsiFile(project: Project): PsiFile? {
return toVirtualFile()?.let { vfile -> PsiManager.getInstance(project).findFile(vfile) }
}
/**
* Returns FqName for given declaration (either Java or Kotlin)
*/
public fun PsiElement.getKotlinFqName(): FqName? {
val element = namedUnwrappedElement
return when (element) {
is PsiPackage -> FqName(element.getQualifiedName())
is PsiClass -> element.getQualifiedName()?.let { FqName(it) }
is PsiMember -> (element : PsiMember).getName()?.let { name ->
val prefix = element.getContainingClass()?.getQualifiedName()
FqName(if (prefix != null) "$prefix.$name" else name)
}
is JetNamedDeclaration -> element.getFqName()
else -> null
}
}
public fun PsiElement.getUsageContext(): PsiElement {
return when (this) {
is JetElement -> PsiTreeUtil.getParentOfType(this, javaClass<JetNamedDeclaration>(), javaClass<JetFile>())!!
@@ -36,7 +36,7 @@ import org.jetbrains.jet.plugin.refactoring.move.moveTopLevelDeclarations.MoveKo
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesUtil
import org.jetbrains.jet.plugin.refactoring.move.moveTopLevelDeclarations.DeferredJetFileKotlinMoveTarget
import org.jetbrains.jet.plugin.refactoring.move.moveTopLevelDeclarations.Mover
import org.jetbrains.jet.plugin.codeInsight.ensureElementsToShortenIsEmptyBeforeRefactoring
import org.jetbrains.jet.plugin.codeInsight.shorten.ensureElementsToShortenIsEmptyBeforeRefactoring
public class MoveKotlinFileHandler : MoveFileHandler() {
private var packageNameInfo: PackageNameInfo? = null
@@ -38,7 +38,7 @@ import org.jetbrains.jet.lang.psi.psiUtil.getPackage
import org.jetbrains.jet.lang.psi.JetFile
import org.jetbrains.jet.plugin.refactoring.move.PackageNameInfo
import org.jetbrains.jet.plugin.refactoring.createKotlinFile
import org.jetbrains.jet.plugin.codeInsight.addToShorteningWaitSet
import org.jetbrains.jet.plugin.codeInsight.shorten.addToShorteningWaitSet
import org.jetbrains.jet.plugin.refactoring.move.getFileNameAfterMove
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
import org.jetbrains.jet.asJava.toLightElements
@@ -64,7 +64,6 @@ import com.intellij.psi.PsiModifierListOwner
import com.intellij.psi.PsiModifier
import com.intellij.util.VisibilityUtil
import com.intellij.openapi.util.Ref
import org.jetbrains.jet.plugin.refactoring.getKotlinFqName
import org.jetbrains.jet.plugin.search.projectScope
import org.jetbrains.jet.plugin.refactoring.move.getInternalReferencesToUpdateOnPackageNameChange
import org.jetbrains.jet.plugin.refactoring.move.createMoveUsageInfo
@@ -72,7 +71,7 @@ import org.jetbrains.jet.plugin.refactoring.move.postProcessMoveUsages
import org.jetbrains.jet.plugin.references.JetSimpleNameReference.ShorteningMode
import org.jetbrains.jet.lang.psi.psiUtil.isAncestor
import org.jetbrains.jet.plugin.refactoring.move.MoveRenameUsageInfoForExtension
import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.plugin.refactoring.fqName.getKotlinFqName
trait Mover: (originalElement: JetNamedDeclaration, targetFile: JetFile) -> JetNamedDeclaration {
object Default: Mover {
@@ -48,7 +48,7 @@ import org.jetbrains.jet.lang.psi.JetImportDirective
import java.util.ArrayList
import com.intellij.refactoring.util.NonCodeUsageInfo
import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper
import org.jetbrains.jet.plugin.refactoring.getKotlinFqName
import org.jetbrains.jet.plugin.refactoring.fqName.getKotlinFqName
import org.jetbrains.jet.lang.psi.JetThisExpression
import org.jetbrains.jet.plugin.references.JetSimpleNameReference.ShorteningMode
import com.intellij.openapi.vfs.VirtualFile
@@ -186,7 +186,7 @@ fun postProcessMoveUsages(usages: List<UsageInfo>,
is MoveRenameUsageInfoForExtension -> {
val element = counterpart(usage.getReferencedElement()!!)
val file = with(usage) { if (addImportToOriginalFile) originalFile else counterpart(originalFile) } as JetFile
ImportInsertHelper.addImportDirectiveIfNeeded(element.getKotlinFqName()!!, file)
ImportInsertHelper.getInstance().addImportDirectiveIfNeeded(element.getKotlinFqName()!!, file)
}
is MoveRenameUsageInfo -> {
@@ -42,7 +42,7 @@ public abstract class AbstractCodeFragmentHighlightingTest : AbstractJetPsiCheck
ApplicationManager.getApplication()?.runWriteAction {
val fileText = FileUtil.loadFile(File(filePath), true)
InTextDirectivesUtils.findListWithPrefixes(fileText, "// IMPORT: ").forEach {
ImportInsertHelper.addImportDirectiveIfNeeded(FqName(it), (myFixture.getFile() as JetFile))
ImportInsertHelper.getInstance().addImportDirectiveIfNeeded(FqName(it), (myFixture.getFile() as JetFile))
}
}
@@ -33,7 +33,7 @@ public class OptimizeImportsOnFlyTest extends LightDaemonAnalyzerTestCase {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ImportInsertHelper.addImportDirectiveIfNeeded(new FqName("java.util.HashSet"), (JetFile) getFile());
ImportInsertHelper.getInstance().addImportDirectiveIfNeeded(new FqName("java.util.HashSet"), (JetFile) getFile());
}
});
}
@@ -46,7 +46,7 @@ public class ImportClassHelperTest extends LightDaemonAnalyzerTestCase {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ImportInsertHelper.addImportDirectiveIfNeeded(new FqName("java.util.ArrayList"), (JetFile) getFile());
ImportInsertHelper.getInstance().addImportDirectiveIfNeeded(new FqName("java.util.ArrayList"), (JetFile) getFile());
}
});
@@ -58,7 +58,7 @@ public class ImportClassHelperTest extends LightDaemonAnalyzerTestCase {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ImportInsertHelper.addImportDirectiveIfNeeded(new FqName("java.util.ArrayList"), (JetFile) getFile());
ImportInsertHelper.getInstance().addImportDirectiveIfNeeded(new FqName("java.util.ArrayList"), (JetFile) getFile());
}
});
@@ -70,7 +70,7 @@ public class ImportClassHelperTest extends LightDaemonAnalyzerTestCase {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ImportInsertHelper.addImportDirectiveIfNeeded(new FqName(importString), (JetFile) getFile());
ImportInsertHelper.getInstance().addImportDirectiveIfNeeded(new FqName(importString), (JetFile) getFile());
}
});
checkResultByFile(getTestName(false) + ".kt.after");