IDEA-91742 (correct conversion of extension methods)

This commit is contained in:
Roman Shevchenko
2012-09-18 17:44:41 +02:00
parent 15cad5b15b
commit f80895f84a
9 changed files with 136 additions and 28 deletions
@@ -966,10 +966,15 @@ public final class PsiUtil extends PsiUtilCore {
}
public static boolean isExtensionMethod(@Nullable final PsiMethod method) {
if (method == null) return false;
return findExtensionMethodMarker(method) != null;
}
@Nullable
public static PsiJavaToken findExtensionMethodMarker(@Nullable final PsiMethod method) {
if (method == null) return null;
final PsiCodeBlock body = method.getBody();
if (body == null) return false;
if (body == null) return null;
final PsiElement previous = PsiTreeUtil.skipSiblingsBackward(body, PsiComment.class, PsiWhiteSpace.class);
return isJavaToken(previous, JavaTokenType.DEFAULT_KEYWORD);
return previous instanceof PsiJavaToken && isJavaToken(previous, JavaTokenType.DEFAULT_KEYWORD) ? (PsiJavaToken)previous : null;
}
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
@@ -31,16 +32,14 @@ import java.util.Collection;
public class ConvertInterfaceToClassIntention extends Intention {
private static void changeInterfaceToClass(PsiClass anInterface)
throws IncorrectOperationException {
private static void changeInterfaceToClass(PsiClass anInterface) throws IncorrectOperationException {
final PsiIdentifier nameIdentifier = anInterface.getNameIdentifier();
assert nameIdentifier != null;
final PsiElement whiteSpace = nameIdentifier.getPrevSibling();
assert whiteSpace != null;
final PsiElement interfaceToken = whiteSpace.getPrevSibling();
assert interfaceToken != null;
final PsiKeyword interfaceKeyword =
(PsiKeyword)interfaceToken.getOriginalElement();
final PsiKeyword interfaceKeyword = (PsiKeyword)interfaceToken.getOriginalElement();
final Project project = anInterface.getProject();
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
final PsiElementFactory factory = psiFacade.getElementFactory();
@@ -52,16 +51,25 @@ public class ConvertInterfaceToClassIntention extends Intention {
return;
}
classModifierList.setModifierProperty(PsiModifier.ABSTRACT, true);
final PsiElement parent = anInterface.getParent();
if (parent instanceof PsiClass) {
classModifierList.setModifierProperty(PsiModifier.STATIC, true);
}
final PsiMethod[] methods = anInterface.getMethods();
for (final PsiMethod method : methods) {
final PsiJavaToken marker = PsiUtil.findExtensionMethodMarker(method);
final PsiModifierList modifierList = method.getModifierList();
modifierList.setModifierProperty(PsiModifier.PUBLIC, true);
modifierList.setModifierProperty(PsiModifier.ABSTRACT, true);
if (marker != null) {
marker.delete();
}
else {
modifierList.setModifierProperty(PsiModifier.ABSTRACT, true);
}
}
final PsiField[] fields = anInterface.getFields();
for (final PsiField field : fields) {
final PsiModifierList modifierList = field.getModifierList();
@@ -71,6 +79,7 @@ public class ConvertInterfaceToClassIntention extends Intention {
modifierList.setModifierProperty(PsiModifier.FINAL, true);
}
}
final PsiClass[] innerClasses = anInterface.getInnerClasses();
for (PsiClass innerClass : innerClasses) {
final PsiModifierList modifierList = innerClass.getModifierList();
@@ -0,0 +1,19 @@
/*
* Copyright 2000-2012 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.
*/
public interface I<caret> {
void m();
}
@@ -0,0 +1,19 @@
/*
* Copyright 2000-2012 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.
*/
public abstract class I {
public abstract void m();
}
@@ -0,0 +1,21 @@
/*
* Copyright 2000-2012 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.
*/
public interface I<caret> {
void m() default {
System.out.println("Hi there.");
}
}
@@ -0,0 +1,21 @@
/*
* Copyright 2000-2012 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.
*/
public abstract class I {
public void m() {
System.out.println("Hi there.");
}
}
@@ -1,6 +0,0 @@
package com.siyeh.ipp.interfacetoclass;
public interface ConvertInterfaceToClass
{
}
@@ -1,14 +0,0 @@
package com.siyeh.ipp.interfacetoclass;
import javax.swing.AbstractAction;
import java.awt.event.ActionEvent;
// make me readonly
public class ConvertInterfaceToClassImpl extends AbstractAction
implements ConvertInterfaceToClass
{
public void actionPerformed(ActionEvent e)
{
}
}
@@ -0,0 +1,34 @@
/*
* Copyright 2000-2012 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 com.siyeh.ipp.interfacetoclass;
import com.siyeh.IntentionPowerPackBundle;
import com.siyeh.ipp.IPPTestCase;
public class ConvertInterfaceToClassTest extends IPPTestCase {
public void testBasic() { doTest(); }
public void testExtensionMethods() { doTest(); }
@Override
protected String getRelativePath() {
return "interfaceToClass";
}
@Override
protected String getIntentionName() {
return IntentionPowerPackBundle.message("convert.interface.to.class.intention.name");
}
}