diff --git a/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/ImplementMethodsHandler.java b/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/ImplementMethodsHandler.java index 57f0952e6783..f16b0e62fe6a 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/ImplementMethodsHandler.java +++ b/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/ImplementMethodsHandler.java @@ -34,12 +34,14 @@ import java.util.Set; */ public class ImplementMethodsHandler extends OverrideImplementMethodsHandler implements IntentionAction { + @Override protected Set collectMethodsToGenerate(MutableClassDescriptor descriptor) { Set missingImplementations = Sets.newLinkedHashSet(); OverrideResolver.collectMissingImplementations(descriptor, missingImplementations, missingImplementations); return missingImplementations; } + @Override protected String getChooserTitle() { return "Implement Members"; } diff --git a/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java b/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java index d4b668ac33f2..58f112044101 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java +++ b/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java @@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.JetStandardLibrary; import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper; +import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.ArrayList; import java.util.Collections; @@ -54,9 +55,10 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns return members; } - public Set collectMethodsToGenerate(JetClassOrObject classOrObject) { + @NotNull + public Set collectMethodsToGenerate(@NotNull JetClassOrObject classOrObject) { BindingContext bindingContext = - WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile)classOrObject.getContainingFile()); + WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile)classOrObject.getContainingFile()); final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); if (descriptor instanceof MutableClassDescriptor) { return collectMethodsToGenerate((MutableClassDescriptor)descriptor); @@ -75,10 +77,6 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns return; } - // NOTE + TODO: If you try to cache findInsertBeforeAnchor element, there will be failed assertion - // "PSI/document inconsistency before reparse: file=" from DocumentCommitThread after inserting two overriding - // with the caret right before existing function start. - PsiElement afterAnchor = findInsertAfterAnchor(editor, body); if (afterAnchor == null) { @@ -115,7 +113,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns } }); - if (offsetCursorElement != null) { + if (offsetCursorElement != null && offsetCursorElement != body.getRBrace()) { afterAnchor = offsetCursorElement; } @@ -130,14 +128,15 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns else { bodyBuilder.append("val "); } - bodyBuilder.append(descriptor.getName()).append(":").append(descriptor.getType()); + bodyBuilder.append(descriptor.getName()).append(" : ").append(DescriptorRenderer.COMPACT.renderTypeWithShortNames( + descriptor.getType())); ImportInsertHelper.addImportDirectiveIfNeeded(descriptor.getType(), file); String initializer = defaultInitializer(descriptor.getType(), JetStandardLibrary.getInstance()); if (initializer != null) { - bodyBuilder.append("=").append(initializer); + bodyBuilder.append(" = ").append(initializer); } else { - bodyBuilder.append("= ?"); + bodyBuilder.append(" = ?"); } return JetPsiFactory.createProperty(project, bodyBuilder.toString()); } @@ -153,16 +152,17 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns } first = false; bodyBuilder.append(parameterDescriptor.getName()); - bodyBuilder.append(":"); - bodyBuilder.append(parameterDescriptor.getType().toString()); + bodyBuilder.append(" : "); + bodyBuilder.append(DescriptorRenderer.COMPACT.renderTypeWithShortNames(parameterDescriptor.getType())); ImportInsertHelper.addImportDirectiveIfNeeded(parameterDescriptor.getType(), file); } bodyBuilder.append(")"); final JetType returnType = descriptor.getReturnType(); final JetStandardLibrary stdlib = JetStandardLibrary.getInstance(); - if (!returnType.equals(stdlib.getTuple0Type())) { - bodyBuilder.append(":").append(returnType.toString()); + + if (returnType != null && !stdlib.getTuple0Type().equals(returnType)) { + bodyBuilder.append(" : ").append(returnType.toString()); ImportInsertHelper.addImportDirectiveIfNeeded(returnType, file); } @@ -183,6 +183,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns else if (returnType.equals(stdlib.getBooleanType())) { return "false"; } + return null; } @@ -209,10 +210,12 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns protected abstract String getNoMethodsFoundHint(); - public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file, - boolean implementAll) { + public void invoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull PsiFile file, boolean implementAll) { final PsiElement elementAtCaret = file.findElementAt(editor.getCaretModel().getOffset()); final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class); + + assert classOrObject != null : "ClassObject should be checked in isValidFor method"; + Set missingImplementations = collectMethodsToGenerate(classOrObject); if (missingImplementations.isEmpty() && !implementAll) { HintManager.getInstance().showErrorHint(editor, getNoMethodsFoundHint()); @@ -225,10 +228,10 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns selectedElements = members; } else { - final MemberChooser chooser = showOverrideImplementChooser(project, - members.toArray( - new DescriptorClassMember[members - .size()])); + final MemberChooser chooser = showOverrideImplementChooser( + project, + members.toArray(new DescriptorClassMember[members.size()])); + if (chooser == null) { return; } diff --git a/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideMethodsHandler.java b/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideMethodsHandler.java index 29e2eb3a4047..72f1bebcd982 100644 --- a/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideMethodsHandler.java +++ b/plugins/kotlin/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideMethodsHandler.java @@ -27,6 +27,7 @@ import java.util.Set; * @author yole */ public class OverrideMethodsHandler extends OverrideImplementMethodsHandler { + @Override protected Set collectMethodsToGenerate(MutableClassDescriptor descriptor) { final Set superMethods = OverrideResolver.collectSuperMethods(descriptor).keySet(); for (CallableMemberDescriptor member : descriptor.getCallableMembers()) { @@ -41,6 +42,7 @@ public class OverrideMethodsHandler extends OverrideImplementMethodsHandler { return result; } + @Override protected String getChooserTitle() { return "Override Members"; } diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java b/plugins/kotlin/idea/tests/test/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java index 43d3e4ad0789..83a8cb9a83d8 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java @@ -49,6 +49,10 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase { myFixture.setTestDataPath(PluginTestCaseBase.getTestDataPathBase() + "/codeInsight/overrideImplement"); } + public void testFunctionProperty() { + doFileTest(); + } + public void testJavaInterfaceMethod() { doDirectoryTest(); } @@ -103,6 +107,7 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase { private void doImplement() { final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset()); final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class); + assertNotNull("Caret should be inside class or object", classOrObject); final Set descriptors = new ImplementMethodsHandler().collectMethodsToGenerate(classOrObject); assertEquals("Invalid number of available descriptors for override", 1, descriptors.size()); new WriteCommandAction(myFixture.getProject(), myFixture.getFile()) { @@ -118,6 +123,7 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase { private void doMultiImplement() { final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset()); final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class); + assertNotNull("Caret should be inside class or object", classOrObject); final Set descriptors = new ImplementMethodsHandler().collectMethodsToGenerate(classOrObject); final ArrayList descriptorsList = new ArrayList(descriptors); diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/functionProperty.kt b/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/functionProperty.kt new file mode 100644 index 000000000000..c8adcbdfe9b7 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/functionProperty.kt @@ -0,0 +1,8 @@ +// From KT-1648 +trait A { + val method:() -> Unit? +} + +fun some() : A { + return object A {} +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/functionProperty.kt.after b/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/functionProperty.kt.after new file mode 100644 index 000000000000..74d3266d01a8 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/codeInsight/overrideImplement/functionProperty.kt.after @@ -0,0 +1,10 @@ +// From KT-1648 +trait A { + val method:() -> Unit? +} + +fun some() : A { + return object A { + override val method : () -> Unit? = ? + } +} \ No newline at end of file