Translate KotlinSafeDeleteProcessor to Kotlin

This commit is contained in:
Alexey Sedunov
2014-01-28 16:48:45 +04:00
parent f80fa8515a
commit 7f74ea5081
15 changed files with 506 additions and 462 deletions
@@ -1,4 +1,8 @@
<root>
<item
name='com.intellij.openapi.util.Conditions com.intellij.openapi.util.Condition&lt;T&gt; or(com.intellij.openapi.util.Condition&lt;T&gt;, com.intellij.openapi.util.Condition&lt;T&gt;)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.intellij.openapi.util.Key com.intellij.openapi.util.Key&lt;T&gt; create(java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
@@ -11,6 +11,9 @@
<item name='com.intellij.psi.PsiElement com.intellij.psi.PsiElement replace(com.intellij.psi.PsiElement)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.intellij.psi.PsiReference com.intellij.psi.PsiElement getElement()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.psi.PsiReferenceService java.util.List&lt;com.intellij.psi.PsiReference&gt; getReferences(com.intellij.psi.PsiElement, com.intellij.psi.PsiReferenceService.Hints)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
@@ -19,4 +19,29 @@
name='com.intellij.psi.search.searches.OverridingMethodsSearch com.intellij.util.Query&lt;com.intellij.psi.PsiMethod&gt; search(com.intellij.psi.PsiMethod, com.intellij.psi.search.SearchScope, boolean)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.psi.search.searches.ReferencesSearch com.intellij.util.Query&lt;com.intellij.psi.PsiReference&gt; search(com.intellij.psi.PsiElement)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value" val="&quot;fun search(element: PsiElement): Query&lt;PsiReference&gt;&quot;"/>
</annotation>
</item>
<item
name='com.intellij.psi.search.searches.ReferencesSearch com.intellij.util.Query&lt;com.intellij.psi.PsiReference&gt; search(com.intellij.psi.PsiElement, com.intellij.psi.search.SearchScope)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value" val="&quot;fun search(element: PsiElement, searchScope: SearchScope): Query&lt;PsiReference&gt;&quot;"/>
</annotation>
</item>
<item
name='com.intellij.psi.search.searches.ReferencesSearch com.intellij.util.Query&lt;com.intellij.psi.PsiReference&gt; search(com.intellij.psi.PsiElement, com.intellij.psi.search.SearchScope, boolean)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun search(element: PsiElement, searchScope: SearchScope, ignoreAccessScope: Boolean): Query&lt;PsiReference&gt;&quot;"/>
</annotation>
</item>
<item
name='com.intellij.psi.search.searches.ReferencesSearch com.intellij.util.Query&lt;com.intellij.psi.PsiReference&gt; search(com.intellij.psi.search.searches.ReferencesSearch.SearchParameters)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -0,0 +1,98 @@
<root>
<item
name='com.intellij.refactoring.safeDelete.JavaSafeDeleteDelegate void createUsageInfoForParameter(com.intellij.psi.PsiReference, java.util.List&lt;com.intellij.usageView.UsageInfo&gt;, com.intellij.psi.PsiParameter, com.intellij.psi.PsiMethod)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun createUsageInfoForParameter(reference: PsiReference, usages: MutableList&lt;UsageInfo&gt;, parameter: PsiParameter, method: PsiMethod): Unit&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor java.util.Collection&lt;? extends com.intellij.psi.PsiElement&gt; getElementsToSearch(com.intellij.psi.PsiElement, com.intellij.openapi.module.Module, java.util.Collection&lt;com.intellij.psi.PsiElement&gt;)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun getElementsToSearch(element: PsiElement, module: Module?, allElementsToDelete: Collection&lt;PsiElement&gt;): Collection&lt;out PsiElement&gt;?&quot;"/>
</annotation>
</item>
<item name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate boolean handlesElement(com.intellij.psi.PsiElement)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value" val="&quot;fun handlesElement(element: PsiElement): Boolean&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate boolean isToSearchForTextOccurrences(com.intellij.psi.PsiElement)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value" val="&quot;fun isToSearchForTextOccurrences(element: PsiElement): Boolean&quot;"/>
</annotation>
</item>
<item name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate boolean isToSearchInComments(com.intellij.psi.PsiElement)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value" val="&quot;fun isToSearchInComments(element: PsiElement): Boolean&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo findUsages(com.intellij.psi.PsiElement, com.intellij.psi.PsiElement[], java.util.List&lt;com.intellij.usageView.UsageInfo&gt;)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun findUsages(element: PsiElement, allElementsToDelete: Array&lt;out PsiElement&gt;, result: MutableList&lt;UsageInfo&gt;): NonCodeUsageSearchInfo?&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate com.intellij.usageView.UsageInfo[] preprocessUsages(com.intellij.openapi.project.Project, com.intellij.usageView.UsageInfo[])'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun preprocessUsages(project: Project, usages: Array&lt;out UsageInfo&gt;): Array&lt;UsageInfo&gt;?&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate java.util.Collection&lt;? extends com.intellij.psi.PsiElement&gt; getElementsToSearch(com.intellij.psi.PsiElement, java.util.Collection&lt;com.intellij.psi.PsiElement&gt;)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun getElementsToSearch(element: PsiElement, allElementsToDelete: Collection&lt;PsiElement&gt;): Collection&lt;out PsiElement&gt;?&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate java.util.Collection&lt;com.intellij.psi.PsiElement&gt; getAdditionalElementsToDelete(com.intellij.psi.PsiElement, java.util.Collection&lt;com.intellij.psi.PsiElement&gt;, boolean)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun getAdditionalElementsToDelete(element: PsiElement, allElementsToDelete: Collection&lt;PsiElement&gt;, askUser: Boolean): MutableCollection&lt;PsiElement&gt;?&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate java.util.Collection&lt;java.lang.String&gt; findConflicts(com.intellij.psi.PsiElement, com.intellij.psi.PsiElement[])'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun findConflicts(element: PsiElement, allElementsToDelete: Array&lt;out PsiElement&gt;): MutableCollection&lt;String&gt;?&quot;"/>
</annotation>
</item>
<item name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate void prepareForDeletion(com.intellij.psi.PsiElement)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value" val="&quot;fun prepareForDeletion(element: PsiElement): Unit&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate void setToSearchForTextOccurrences(com.intellij.psi.PsiElement, boolean)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value" val="&quot;fun setToSearchForTextOccurrences(element: PsiElement, enabled: Boolean): Unit&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegate void setToSearchInComments(com.intellij.psi.PsiElement, boolean)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value" val="&quot;fun setToSearchInComments(element: PsiElement, enabled: Boolean): Unit&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegateBase java.util.Collection&lt;? extends com.intellij.psi.PsiElement&gt; getElementsToSearch(com.intellij.psi.PsiElement, com.intellij.openapi.module.Module, java.util.Collection&lt;com.intellij.psi.PsiElement&gt;)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun getElementsToSearch(element: PsiElement, module: Module?, allElementsToDelete: Collection&lt;PsiElement&gt;): Collection&lt;out PsiElement&gt;?&quot;"/>
</annotation>
</item>
<item
name='com.intellij.refactoring.safeDelete.SafeDeleteProcessorDelegateBase java.util.Collection&lt;? extends com.intellij.psi.PsiElement&gt; getElementsToSearch(com.intellij.psi.PsiElement, java.util.Collection&lt;com.intellij.psi.PsiElement&gt;)'>
<annotation name='jet.runtime.typeinfo.KotlinSignature'>
<val name="value"
val="&quot;fun getElementsToSearch(element: PsiElement, allElementsToDelete: Collection&lt;PsiElement&gt;): Collection&lt;out PsiElement&gt;?&quot;"/>
</annotation>
</item>
</root>
@@ -0,0 +1,8 @@
<root>
<item name='com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteUsageInfo com.intellij.psi.PsiElement getReferencedElement()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteUsageInfo myReferencedElement'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -0,0 +1,8 @@
<root>
<item name='com.intellij.usageView.UsageInfo com.intellij.psi.SmartPsiElementPointer&lt;?&gt; getSmartPointer()'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item name='com.intellij.usageView.UsageInfo mySmartPointer'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
</root>
@@ -39,6 +39,9 @@ import com.intellij.psi.PsiNamedElement
import com.intellij.psi.PsiNamedElement
import org.jetbrains.jet.lang.psi.JetCallableDeclaration
import org.jetbrains.jet.lang.psi.psiUtil.isExtensionDeclaration
import com.intellij.psi.PsiClass
fun JetClassOrObject.toLightClass(): PsiClass? = LightClassUtil.getPsiClass(this)
fun JetDeclaration.toLightElements(): List<PsiElement> =
when (this) {
@@ -16,11 +16,13 @@
package org.jetbrains.jet.lang.descriptors;
import jet.runtime.typeinfo.KotlinSignature;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
public interface CallableMemberDescriptor extends CallableDescriptor, MemberDescriptor {
@KotlinSignature("fun getOverriddenDescriptors(): MutableSet<out CallableMemberDescriptor>")
@NotNull
@Override
Set<? extends CallableMemberDescriptor> getOverriddenDescriptors();
@@ -25,12 +25,12 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.plugin.refactoring.changeSignature.JetChangeSignatureHandler;
import org.jetbrains.jet.plugin.refactoring.introduceVariable.JetIntroduceVariableHandler;
import org.jetbrains.jet.plugin.refactoring.safeDelete.KotlinSafeDeleteProcessor;
import org.jetbrains.jet.plugin.refactoring.safeDelete.SafeDeletePackage;
public class JetRefactoringSupportProvider extends RefactoringSupportProvider {
@Override
public boolean isSafeDeleteAvailable(@NotNull PsiElement element) {
return KotlinSafeDeleteProcessor.canDeleteElement(element);
return SafeDeletePackage.canDeleteElement(element);
}
@Override
@@ -34,6 +34,7 @@ import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.ui.components.JBList;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import jet.runtime.typeinfo.KotlinSignature;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.asJava.AsJavaPackage;
@@ -117,6 +118,8 @@ public class JetRefactoringUtil {
return markAsJava ? "[Java] " + description : description;
}
@KotlinSignature(
"fun checkSuperMethods(declaration: JetDeclaration, ignore: Collection<PsiElement>?, actionStringKey: String): MutableList<out PsiElement>?")
@Nullable
public static List<? extends PsiElement> checkSuperMethods(
@NotNull JetDeclaration declaration, @Nullable Collection<PsiElement> ignore, @NotNull String actionStringKey
@@ -287,6 +290,7 @@ public class JetRefactoringUtil {
return "class " + classOrObject.getName();
}
@KotlinSignature("fun checkParametersInMethodHierarchy(parameter: PsiParameter): MutableCollection<out PsiElement>?")
@Nullable
public static Collection<? extends PsiElement> checkParametersInMethodHierarchy(@NotNull PsiParameter parameter) {
PsiMethod method = (PsiMethod)parameter.getDeclarationScope();
@@ -1,3 +1,19 @@
/*
* 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.safeDelete;
import com.intellij.psi.PsiElement;
@@ -30,6 +30,7 @@ import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.table.JBTable;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.impl.UsagePreviewPanel;
import jet.runtime.typeinfo.KotlinSignature;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
@@ -116,6 +117,7 @@ class KotlinOverridingDialog extends DialogWrapper {
return "#org.jetbrains.jet.plugin.refactoring.safeDelete.KotlinOverridingDialog";
}
@KotlinSignature("fun getSelected(): ArrayList<UsageInfo>")
public ArrayList<UsageInfo> getSelected() {
ArrayList<UsageInfo> result = new ArrayList<UsageInfo>();
for (int i = 0; i < myChecked.length; i++) {
@@ -1,460 +0,0 @@
/*
* Copyright 2010-2013 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.safeDelete;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Conditions;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiReference;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor;
import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverrideAnnotation;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodUsageInfo;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceJavaDeleteUsageInfo;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.asJava.AsJavaPackage;
import org.jetbrains.jet.asJava.LightClassUtil;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.Modality;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetBundle;
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
import org.jetbrains.jet.plugin.refactoring.JetRefactoringUtil;
import org.jetbrains.jet.plugin.references.JetPsiReference;
import java.util.*;
public class KotlinSafeDeleteProcessor extends JavaSafeDeleteProcessor {
public static boolean canDeleteElement(@NotNull PsiElement element) {
if (PsiUtilPackage.isObjectLiteral(element)) return false;
if (element instanceof JetParameter) {
JetDeclaration declaration = PsiTreeUtil.getParentOfType(element, JetDeclaration.class);
return declaration != null && !(declaration instanceof JetPropertyAccessor && ((JetPropertyAccessor) declaration).isSetter());
}
return element instanceof JetClassOrObject
|| element instanceof JetNamedFunction
|| element instanceof PsiMethod
|| element instanceof JetProperty
|| element instanceof JetTypeParameter;
}
@Override
public boolean handlesElement(@NotNull PsiElement element) {
return canDeleteElement(element);
}
@NotNull
protected static NonCodeUsageSearchInfo getSearchInfo(
@NotNull PsiElement element, @NotNull Collection<? extends PsiElement> ignoredElements
) {
return new NonCodeUsageSearchInfo(getCondition(ignoredElements), element);
}
private static Condition<PsiElement> getCondition(final Collection<? extends PsiElement> ignoredElements) {
return new Condition<PsiElement>() {
@Override
public boolean value(PsiElement usage) {
if (usage instanceof JetFile) return false;
return isInside(usage, ignoredElements);
}
};
}
@NotNull
protected static NonCodeUsageSearchInfo getSearchInfo(@NotNull PsiElement element, @NotNull PsiElement[] ignoredElements) {
return getSearchInfo(element, Arrays.asList(ignoredElements));
}
@Nullable
@Override
public NonCodeUsageSearchInfo findUsages(
@NotNull PsiElement element, @NotNull PsiElement[] allElementsToDelete, @NotNull List<UsageInfo> result
) {
if (element instanceof JetClassOrObject) {
return delegateToJavaProcessor(LightClassUtil.getPsiClass((JetClassOrObject) element), allElementsToDelete, result);
}
if (element instanceof JetNamedFunction) {
JetNamedFunction function = (JetNamedFunction) element;
if (function.isLocal()) {
return findKotlinDeclarationUsages(function, allElementsToDelete, result);
}
PsiMethod method = LightClassUtil.getLightClassMethod((JetNamedFunction) element);
if (method != null) return delegateToJavaProcessor(method, allElementsToDelete, result);
return getSearchInfo(element, allElementsToDelete);
}
if (element instanceof PsiMethod) {
return delegateToJavaProcessor(element, allElementsToDelete, result);
}
if (element instanceof JetProperty) {
JetProperty property = (JetProperty) element;
if (property.isLocal()) return findKotlinDeclarationUsages(property, allElementsToDelete, result);
return delegateToJavaProcessor(property, allElementsToDelete, result);
}
if (element instanceof JetTypeParameter) {
JetTypeParameter typeParameter = (JetTypeParameter) element;
findTypeParameterUsages(typeParameter, result);
return delegateToJavaProcessor(typeParameter, allElementsToDelete, result);
}
if (element instanceof JetParameter) {
return delegateToJavaProcessor((JetParameter) element, allElementsToDelete, result);
}
return getSearchInfo(element, allElementsToDelete);
}
private NonCodeUsageSearchInfo delegateToJavaProcessor(
JetDeclaration jetDeclaration,
PsiElement[] allElementsToDelete,
List<UsageInfo> result
) {
return new NonCodeUsageSearchInfo(
delegateToJavaProcessorAndCombineConditions(
AsJavaPackage.toLightElements(jetDeclaration),
getCondition(Arrays.asList(allElementsToDelete)),
allElementsToDelete,
result
),
jetDeclaration
);
}
private Condition<PsiElement> delegateToJavaProcessorAndCombineConditions(
Iterable<? extends PsiElement> elements,
Condition<PsiElement> insideDeleted,
PsiElement[] allElementsToDelete,
List<UsageInfo> result
) {
for (PsiElement element: elements) {
NonCodeUsageSearchInfo accessorSearchInfo = delegateToJavaProcessor(element, allElementsToDelete, result);
if (accessorSearchInfo == null) continue;
insideDeleted = Conditions.or(insideDeleted, accessorSearchInfo.getInsideDeletedCondition());
}
return insideDeleted;
}
@SuppressWarnings("MethodOverridesPrivateMethodOfSuperclass")
protected static boolean isInside(@NotNull PsiElement place, @NotNull PsiElement[] ancestors) {
return isInside(place, Arrays.asList(ancestors));
}
@SuppressWarnings("MethodOverridesPrivateMethodOfSuperclass")
protected static boolean isInside(@NotNull PsiElement place, @NotNull Collection<? extends PsiElement> ancestors) {
for (PsiElement element : ancestors) {
if (isInside(place, element)) return true;
}
return false;
}
@SuppressWarnings("MethodOverridesStaticMethodOfSuperclass")
public static boolean isInside(@NotNull PsiElement place, @NotNull PsiElement ancestor) {
return JavaSafeDeleteProcessor.isInside(place, AsJavaPackage.getUnwrapped(ancestor));
}
@Nullable
protected NonCodeUsageSearchInfo delegateToJavaProcessor(
@Nullable PsiElement element,
@NotNull PsiElement[] allElementsToDelete,
@NotNull List<UsageInfo> result
) {
if (element == null) return null;
List<UsageInfo> javaUsages = new ArrayList<UsageInfo>();
NonCodeUsageSearchInfo searchInfo = super.findUsages(element, allElementsToDelete, javaUsages);
for (UsageInfo usageInfo : javaUsages) {
if (usageInfo instanceof SafeDeleteOverridingMethodUsageInfo) {
SafeDeleteOverridingMethodUsageInfo overrideUsageInfo = (SafeDeleteOverridingMethodUsageInfo) usageInfo;
PsiElement usageElement = overrideUsageInfo.getSmartPointer().getElement();
usageInfo = (usageElement != null)
? new KotlinSafeDeleteOverridingUsageInfo(usageElement, overrideUsageInfo.getReferencedElement())
: null;
}
else if (usageInfo instanceof SafeDeleteOverrideAnnotation) {
SafeDeleteOverrideAnnotation overrideAnnotationUsageInfo = (SafeDeleteOverrideAnnotation) usageInfo;
PsiElement targetElement = overrideAnnotationUsageInfo.getSmartPointer().getElement();
if (targetElement != null) {
boolean noSuperMethods = ContainerUtil.and(
AsJavaPackage.toLightMethods(targetElement),
new Condition<PsiMethod>() {
@Override
public boolean value(PsiMethod method) {
return method.findSuperMethods().length == 0;
}
}
);
usageInfo = noSuperMethods
? new KotlinSafeDeleteOverrideAnnotation(targetElement, overrideAnnotationUsageInfo.getReferencedElement())
: null;
}
else {
usageInfo = null;
}
}
else if (usageInfo instanceof SafeDeleteReferenceJavaDeleteUsageInfo) {
SafeDeleteReferenceJavaDeleteUsageInfo javaDeleteUsageInfo = (SafeDeleteReferenceJavaDeleteUsageInfo) usageInfo;
PsiElement usageElement = javaDeleteUsageInfo.getElement();
JetImportDirective importDirective = PsiTreeUtil.getParentOfType(usageElement, JetImportDirective.class, false);
if (importDirective != null) {
usageInfo = new SafeDeleteImportDirectiveUsageInfo(
importDirective, (JetDeclaration) AsJavaPackage.getUnwrapped(element)
);
}
}
if (usageInfo != null) {
result.add(usageInfo);
}
}
return searchInfo;
}
@NotNull
protected static NonCodeUsageSearchInfo findKotlinDeclarationUsages(
@NotNull final JetDeclaration declaration,
@NotNull final PsiElement[] allElementsToDelete,
@NotNull final List<UsageInfo> result
) {
ReferencesSearch.search(declaration, declaration.getUseScope()).forEach(new Processor<PsiReference>() {
@Override
public boolean process(PsiReference reference) {
PsiElement element = reference.getElement();
if (!isInside(element, allElementsToDelete)) {
JetImportDirective importDirective = PsiTreeUtil.getParentOfType(element, JetImportDirective.class, false);
if (importDirective != null) {
result.add(new SafeDeleteImportDirectiveUsageInfo(importDirective, declaration));
}
else {
result.add(new SafeDeleteReferenceSimpleDeleteUsageInfo(element, declaration, false));
}
}
return true;
}
});
return getSearchInfo(declaration, allElementsToDelete);
}
protected static void findTypeParameterUsages(
@NotNull final JetTypeParameter parameter,
@NotNull final List<UsageInfo> result
) {
JetTypeParameterListOwner owner = PsiTreeUtil.getParentOfType(parameter, JetTypeParameterListOwner.class);
if (owner == null) return;
List<JetTypeParameter> parameterList = owner.getTypeParameters();
final int parameterIndex = parameterList.indexOf(parameter);
ReferencesSearch.search(owner).forEach(
new Processor<PsiReference>() {
@Override
public boolean process(PsiReference reference) {
if (reference instanceof JetPsiReference) {
processKotlinTypeArgumentListCandidate(reference, parameterIndex, result, parameter);
}
return true;
}
}
);
}
private static void processKotlinTypeArgumentListCandidate(
@NotNull PsiReference reference,
int parameterIndex,
@NotNull List<UsageInfo> result,
@NotNull JetTypeParameter parameter
) {
PsiElement referencedElement = reference.getElement();
JetTypeArgumentList argList = null;
JetUserType type = PsiTreeUtil.getParentOfType(referencedElement, JetUserType.class);
if (type != null) {
argList = type.getTypeArgumentList();
}
else {
JetCallExpression callExpression = PsiTreeUtil.getParentOfType(referencedElement, JetCallExpression.class);
if (callExpression != null) {
argList = callExpression.getTypeArgumentList();
}
}
if (argList != null) {
List<JetTypeProjection> projections = argList.getArguments();
if (parameterIndex < projections.size()) {
result.add(new SafeDeleteTypeArgumentListUsageInfo(projections.get(parameterIndex), parameter));
}
}
}
@Override
@Nullable
public Collection<String> findConflicts(@NotNull PsiElement element, @NotNull PsiElement[] allElementsToDelete) {
if (element instanceof JetNamedFunction || element instanceof JetProperty) {
JetClass jetClass = PsiTreeUtil.getParentOfType(element, JetClass.class);
if (jetClass == null || jetClass.getBody() != element.getParent()) return null;
JetModifierList modifierList = jetClass.getModifierList();
if (modifierList != null && modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD)) return null;
BindingContext bindingContext =
AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) element.getContainingFile()).getBindingContext();
DeclarationDescriptor declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
if (!(declarationDescriptor instanceof CallableMemberDescriptor)) return null;
List<String> messages = new ArrayList<String>();
CallableMemberDescriptor callableDescriptor = (CallableMemberDescriptor) declarationDescriptor;
for (CallableMemberDescriptor overridenDescriptor : callableDescriptor.getOverriddenDescriptors()) {
if (overridenDescriptor.getModality() == Modality.ABSTRACT) {
String message = JetBundle.message(
"x.implements.y",
JetRefactoringUtil.formatFunction(callableDescriptor, bindingContext, true),
JetRefactoringUtil.formatClass(callableDescriptor.getContainingDeclaration(), bindingContext, true),
JetRefactoringUtil.formatFunction(overridenDescriptor, bindingContext, true),
JetRefactoringUtil.formatClass(overridenDescriptor.getContainingDeclaration(), bindingContext, true)
);
messages.add(message);
}
}
if (!messages.isEmpty()) return messages;
}
return super.findConflicts(element, allElementsToDelete);
}
/*
* Mostly copied from JavaSafeDeleteProcessor.preprocessUsages
* Revision: d4fc033
* (replaced original dialog)
*/
@Nullable
@Override
public UsageInfo[] preprocessUsages(@NotNull Project project, @NotNull UsageInfo[] usages) {
ArrayList<UsageInfo> result = new ArrayList<UsageInfo>();
ArrayList<UsageInfo> overridingMethodUsages = new ArrayList<UsageInfo>();
for (UsageInfo usage : usages) {
if (usage instanceof KotlinSafeDeleteOverridingUsageInfo) {
overridingMethodUsages.add(usage);
}
else {
result.add(usage);
}
}
if (!overridingMethodUsages.isEmpty()) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
result.addAll(overridingMethodUsages);
}
else {
KotlinOverridingDialog dialog = new KotlinOverridingDialog(project, overridingMethodUsages);
dialog.show();
if (!dialog.isOK()) return null;
result.addAll(dialog.getSelected());
}
}
return result.toArray(new UsageInfo[result.size()]);
}
@Override
public void prepareForDeletion(@NotNull PsiElement element) throws IncorrectOperationException {
if (element instanceof PsiMethod) {
SafeDeletePackage.cleanUpOverrides((PsiMethod) element);
}
else if (element instanceof JetNamedFunction) {
PsiMethod lightMethod = LightClassUtil.getLightClassMethod((JetNamedFunction) element);
if (lightMethod == null) {
return;
}
SafeDeletePackage.cleanUpOverrides(lightMethod);
}
else if (element instanceof JetProperty) {
LightClassUtil.PropertyAccessorsPsiMethods propertyMethods =
LightClassUtil.getLightClassPropertyMethods((JetProperty) element);
PsiMethod getter = propertyMethods.getGetter();
PsiMethod setter = propertyMethods.getSetter();
if (getter != null) {
SafeDeletePackage.cleanUpOverrides(getter);
}
if (setter != null) {
SafeDeletePackage.cleanUpOverrides(setter);
}
}
else if (element instanceof JetTypeParameter) {
PsiUtilPackage.deleteElementAndCleanParent(element);
}
else if (element instanceof JetParameter) {
JetPsiUtil.deleteElementWithDelimiters(element);
}
}
@Nullable
@Override
public Collection<? extends PsiElement> getElementsToSearch(
@NotNull PsiElement element, @Nullable Module module, @NotNull Collection<PsiElement> allElementsToDelete
) {
if (element instanceof JetParameter) {
PsiParameter psiParameter = AsJavaPackage.toPsiParameter((JetParameter) element);
if (psiParameter != null) return JetRefactoringUtil.checkParametersInMethodHierarchy(psiParameter);
}
if (element instanceof PsiParameter) {
return JetRefactoringUtil.checkParametersInMethodHierarchy((PsiParameter) element);
}
if (ApplicationManager.getApplication().isUnitTestMode()) {
return Collections.singletonList(element);
}
if (element instanceof JetNamedFunction || element instanceof JetProperty) {
return JetRefactoringUtil.checkSuperMethods(
(JetDeclaration) element, allElementsToDelete, "super.methods.delete.with.usage.search"
);
}
return super.getElementsToSearch(element, module, allElementsToDelete);
}
}
@@ -0,0 +1,310 @@
/*
* 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.safeDelete
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Condition
import com.intellij.openapi.util.Conditions
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiParameter
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.refactoring.safeDelete.JavaSafeDeleteProcessor
import com.intellij.refactoring.safeDelete.NonCodeUsageSearchInfo
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverrideAnnotation
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodUsageInfo
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceJavaDeleteUsageInfo
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteReferenceSimpleDeleteUsageInfo
import com.intellij.usageView.UsageInfo
import org.jetbrains.jet.asJava.*
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor
import org.jetbrains.jet.lang.descriptors.Modality
import org.jetbrains.jet.lang.psi.*
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.plugin.JetBundle
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.plugin.refactoring.JetRefactoringUtil
import org.jetbrains.jet.plugin.references.JetPsiReference
import java.util.*
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
import org.jetbrains.jet.lang.psi.psiUtil.deleteElementAndCleanParent
public class KotlinSafeDeleteProcessor : JavaSafeDeleteProcessor() {
override fun handlesElement(element: PsiElement): Boolean = element.canDeleteElement()
override fun findUsages(
element: PsiElement, allElementsToDelete: Array<out PsiElement>, usages: MutableList<UsageInfo>
): NonCodeUsageSearchInfo {
val deleteList = allElementsToDelete.toList()
fun getIgnoranceCondition(): Condition<PsiElement> {
return object : Condition<PsiElement> {
override fun value(t: PsiElement?): Boolean {
if (t is JetFile) return false
return deleteList.any { element -> JavaSafeDeleteProcessor.isInside(t, element.unwrapped) }
}
}
}
fun getSearchInfo(element: PsiElement): NonCodeUsageSearchInfo {
return NonCodeUsageSearchInfo(getIgnoranceCondition(), element)
}
fun findUsagesByJavaProcessor(element: PsiElement): NonCodeUsageSearchInfo? {
val javaUsages = ArrayList<UsageInfo>()
val searchInfo = super.findUsages(element, allElementsToDelete, javaUsages)
javaUsages.map { usageInfo ->
when (usageInfo) {
is SafeDeleteOverridingMethodUsageInfo ->
usageInfo.getSmartPointer().getElement()?.let { usageElement ->
KotlinSafeDeleteOverridingUsageInfo(usageElement, usageInfo.getReferencedElement())
}
is SafeDeleteOverrideAnnotation ->
usageInfo.getSmartPointer().getElement()?.let { usageElement ->
if (usageElement.toLightMethods().all { method -> method.findSuperMethods().size == 0 }) {
KotlinSafeDeleteOverrideAnnotation(usageElement, usageInfo.getReferencedElement())
}
else null
}
is SafeDeleteReferenceJavaDeleteUsageInfo ->
usageInfo.getElement()?.let { usageElement ->
if (usageElement.getParentByType(javaClass<JetValueArgumentName>()) != null) null
else {
usageElement.getParentByType(javaClass<JetImportDirective>())?.let { importDirective ->
SafeDeleteImportDirectiveUsageInfo(importDirective, element.unwrapped as JetDeclaration)
} ?: usageInfo
}
}
else -> usageInfo
}
}.filterNotNull().toCollection(usages)
return searchInfo
}
fun findUsagesByJavaProcessor(elements: Iterator<PsiElement>, insideDeleted: Condition<PsiElement>): Condition<PsiElement> =
elements
.map { element -> findUsagesByJavaProcessor(element)?.getInsideDeletedCondition() }
.filterNotNull()
.fold(insideDeleted) {(condition1, condition2) -> Conditions.or(condition1, condition2) }
fun findUsagesByJavaProcessor(jetDeclaration: JetDeclaration): NonCodeUsageSearchInfo {
return NonCodeUsageSearchInfo(
findUsagesByJavaProcessor(
jetDeclaration.toLightElements().iterator(),
getIgnoranceCondition()
),
jetDeclaration
)
}
fun findKotlinDeclarationUsages(declaration: JetDeclaration): NonCodeUsageSearchInfo {
ReferencesSearch.search(declaration, declaration.getUseScope())
.iterator()
.filterNot { reference -> getIgnoranceCondition().value(reference.getElement()) }
.mapTo(usages) { reference ->
reference.getElement().getParentByType(javaClass<JetImportDirective>())?.let { importDirective ->
SafeDeleteImportDirectiveUsageInfo(importDirective, element.unwrapped as JetDeclaration)
} ?: SafeDeleteReferenceSimpleDeleteUsageInfo(element, declaration, false)
}
return getSearchInfo(declaration)
}
fun findTypeParameterUsages(parameter: JetTypeParameter) {
val owner = parameter.getParentByType(javaClass<JetTypeParameterListOwner>())
if (owner == null) return
val parameterList = owner.getTypeParameters()
val parameterIndex = parameterList.indexOf(parameter)
for (reference in ReferencesSearch.search(owner)) {
if (reference !is JetPsiReference) continue
val referencedElement = reference.getElement()
val argList = referencedElement.getParentByType(javaClass<JetUserType>())?.let { jetType ->
jetType.getTypeArgumentList()
} ?: referencedElement.getParentByType(javaClass<JetCallExpression>())?.let { callExpression ->
callExpression.getTypeArgumentList()
} ?: null
if (argList != null) {
val projections = argList.getArguments()
if (parameterIndex < projections.size()) {
usages.add(SafeDeleteTypeArgumentListUsageInfo(projections.get(parameterIndex), parameter))
}
}
}
}
val searchInfo = when (element) {
is JetClassOrObject ->
element.toLightClass()?.let { klass -> findUsagesByJavaProcessor(klass) }
is JetNamedFunction -> {
if (element.isLocal()) {
findKotlinDeclarationUsages(element)
}
else {
element.getRepresentativeLightMethod()?.let { method -> findUsagesByJavaProcessor(method) }
}
}
is PsiMethod ->
findUsagesByJavaProcessor(element)
is JetProperty -> {
if (element.isLocal()) {
findKotlinDeclarationUsages(element)
}
else {
findUsagesByJavaProcessor(element)
}
}
is JetTypeParameter -> {
findTypeParameterUsages(element)
findUsagesByJavaProcessor(element)
}
is JetParameter ->
findUsagesByJavaProcessor(element)
else -> null
}
return if (searchInfo != null) searchInfo else getSearchInfo(element)
}
override fun findConflicts(element: PsiElement, allElementsToDelete: Array<out PsiElement>): MutableCollection<String>? {
if (element is JetNamedFunction || element is JetProperty) {
val jetClass = element.getParentByType(javaClass<JetClass>())
if (jetClass == null || jetClass.getBody() != element.getParent()) return null
val modifierList = jetClass.getModifierList()
if (modifierList != null && modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD)) return null
val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element as JetElement)
val declarationDescriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element)
if (declarationDescriptor !is CallableMemberDescriptor) return null
return declarationDescriptor.getOverriddenDescriptors()
.iterator()
.filter { overridenDescriptor -> overridenDescriptor.getModality() == Modality.ABSTRACT }
.mapTo(ArrayList<String>()) { overridenDescriptor ->
JetBundle.message(
"x.implements.y",
JetRefactoringUtil.formatFunction(declarationDescriptor, bindingContext, true),
JetRefactoringUtil.formatClass(declarationDescriptor.getContainingDeclaration(), bindingContext, true),
JetRefactoringUtil.formatFunction(overridenDescriptor, bindingContext, true),
JetRefactoringUtil.formatClass(overridenDescriptor.getContainingDeclaration(), bindingContext, true)
)
}
}
return super.findConflicts(element, allElementsToDelete)
}
/*
* Mostly copied from JavaSafeDeleteProcessor.preprocessUsages
* Revision: d4fc033
* (replaced original dialog)
*/
override fun preprocessUsages(project: Project, usages: Array<out UsageInfo>): Array<UsageInfo>? {
val result = ArrayList<UsageInfo>()
val overridingMethodUsages = ArrayList<UsageInfo>()
for (usage in usages) {
if (usage is KotlinSafeDeleteOverridingUsageInfo) {
overridingMethodUsages.add(usage)
} else {
result.add(usage)
}
}
if (!overridingMethodUsages.isEmpty()) {
if (ApplicationManager.getApplication()!!.isUnitTestMode()) {
result.addAll(overridingMethodUsages)
} else {
val dialog = KotlinOverridingDialog(project, overridingMethodUsages)
dialog.show()
if (!dialog.isOK()) return null
result.addAll(dialog.getSelected())
}
}
return result.copyToArray()
}
override fun prepareForDeletion(element: PsiElement) {
when (element) {
is PsiMethod -> element.cleanUpOverrides()
is JetNamedFunction ->
if (!element.isLocal()) {
element.getRepresentativeLightMethod()?.cleanUpOverrides()
}
is JetProperty ->
if (!element.isLocal()) {
element.toLightMethods().forEach { method -> method.cleanUpOverrides() }
}
is JetTypeParameter ->
element.deleteElementAndCleanParent()
is JetParameter ->
JetPsiUtil.deleteElementWithDelimiters(element)
}
}
override fun getElementsToSearch(
element: PsiElement, module: Module?, allElementsToDelete: Collection<PsiElement>
): Collection<PsiElement>? {
when (element) {
is JetParameter ->
return element.toPsiParameter()?.let { psiParameter ->
JetRefactoringUtil.checkParametersInMethodHierarchy(psiParameter)
} ?: Collections.singletonList(element)
is PsiParameter ->
return JetRefactoringUtil.checkParametersInMethodHierarchy(element)
}
if (ApplicationManager.getApplication()!!.isUnitTestMode()) return Collections.singletonList(element)
return when (element) {
is JetNamedFunction, is JetProperty ->
JetRefactoringUtil.checkSuperMethods(
element as JetDeclaration, allElementsToDelete, "super.methods.delete.with.usage.search"
)
else -> super.getElementsToSearch(element, module, allElementsToDelete)
}
}
}
@@ -26,6 +26,27 @@ import org.jetbrains.jet.lang.psi.JetPsiUtil
import com.intellij.psi.search.searches.OverridingMethodsSearch
import org.jetbrains.jet.asJava.unwrapped
import java.util.ArrayList
import org.jetbrains.jet.lang.psi.JetParameter
import org.jetbrains.jet.lang.psi.JetDeclaration
import org.jetbrains.jet.lang.psi.JetPropertyAccessor
import org.jetbrains.jet.lang.psi.JetClassOrObject
import org.jetbrains.jet.lang.psi.JetTypeParameter
import org.jetbrains.jet.lang.psi.psiUtil.*
public fun PsiElement.canDeleteElement(): Boolean {
if (isObjectLiteral()) return false
if (this is JetParameter) {
val declaration = getParentByType(javaClass<JetDeclaration>(), true)
return declaration != null && !(declaration is JetPropertyAccessor && declaration.isSetter())
}
return this is JetClassOrObject
|| this is JetNamedFunction
|| this is PsiMethod
|| this is JetProperty
|| this is JetTypeParameter
}
fun PsiElement.removeOverrideModifier() {
val modifier = when (this) {