diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java index 456c06fe8756..8ae9622f3440 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaGenerateMemberCompletionContributor.java @@ -23,11 +23,9 @@ import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.Key; import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; -import com.intellij.psi.util.MethodSignature; -import com.intellij.psi.util.PsiFormatUtil; -import com.intellij.psi.util.PsiFormatUtilBase; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.*; import com.intellij.ui.RowIcon; +import com.intellij.util.ObjectUtils; import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.ContainerUtil; @@ -54,17 +52,26 @@ public class JavaGenerateMemberCompletionContributor { if (psiElement(PsiIdentifier.class).withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiClass.class). andNot(JavaCompletionData.AFTER_DOT). andNot(psiElement().afterLeaf(psiElement().inside(PsiModifierList.class))).accepts(position)) { - final PsiClass parent = CompletionUtil.getOriginalElement((PsiClass)position.getParent().getParent().getParent()); - if (parent != null) { - Set addedSignatures = ContainerUtil.newHashSet(); - addGetterSetterElements(result, parent, addedSignatures); - addSuperSignatureElements(parent, true, result, addedSignatures); - addSuperSignatureElements(parent, false, result, addedSignatures); - } + suggestGeneratedMethods(result, position); + } else if (psiElement(PsiIdentifier.class) + .withParents(PsiJavaCodeReferenceElement.class, PsiAnnotation.class, PsiModifierList.class, PsiClass.class).accepts(position)) { + PsiAnnotation annotation = ObjectUtils.assertNotNull(PsiTreeUtil.getParentOfType(position, PsiAnnotation.class)); + int annoStart = annotation.getTextRange().getStartOffset(); + suggestGeneratedMethods(result.withPrefixMatcher(annotation.getText().substring(0, parameters.getOffset() - annoStart)), position); } } + private static void suggestGeneratedMethods(CompletionResultSet result, PsiElement position) { + PsiClass parent = CompletionUtil.getOriginalElement(ObjectUtils.assertNotNull(PsiTreeUtil.getParentOfType(position, PsiClass.class))); + if (parent != null) { + Set addedSignatures = ContainerUtil.newHashSet(); + addGetterSetterElements(result, parent, addedSignatures); + addSuperSignatureElements(parent, true, result, addedSignatures); + addSuperSignatureElements(parent, false, result, addedSignatures); + } + } + private static void addGetterSetterElements(CompletionResultSet result, PsiClass parent, Set addedSignatures) { List prototypes = ContainerUtil.newArrayList(); for (PsiField field : parent.getFields()) { @@ -148,8 +155,9 @@ public class JavaGenerateMemberCompletionContributor { String parameters = PsiFormatUtil.formatMethod(prototype, substitutor, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME); + String overrideSignature = " @Override " + signature; // leading space to make it a middle match, under all annotation suggestions LookupElementBuilder element = LookupElementBuilder.create(prototype, signature).withLookupString(methodName). - withLookupString(signature).withInsertHandler(insertHandler). + withLookupString(signature).withLookupString(overrideSignature).withInsertHandler(insertHandler). appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(typeText).withIcon(icon); element.putUserData(GENERATE_ELEMENT, true); return element; diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingReturnExpressionFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingReturnExpressionFixer.java index 3b07d684b3be..eb68dd4979f7 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingReturnExpressionFixer.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingReturnExpressionFixer.java @@ -83,7 +83,7 @@ public class MissingReturnExpressionFixer implements Fixer { if (!(prev instanceof PsiJavaToken)) { int offset = returnStatement.getTextRange().getEndOffset(); - final PsiMethod method = PsiTreeUtil.getParentOfType(returnStatement, PsiMethod.class); + final PsiMethod method = PsiTreeUtil.getParentOfType(returnStatement, PsiMethod.class, true, PsiLambdaExpression.class); if (method != null && method.getReturnType() == PsiType.VOID) { offset = returnStatement.getTextRange().getStartOffset() + "return".length(); } diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SemicolonFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SemicolonFixer.java index 66badf559cee..e2a70bc2f116 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SemicolonFixer.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SemicolonFixer.java @@ -47,7 +47,7 @@ public class SemicolonFixer implements Fixer { private static boolean fixReturn(@NotNull Editor editor, @Nullable PsiElement psiElement) { if (psiElement instanceof PsiReturnStatement) { - PsiMethod method = PsiTreeUtil.getParentOfType(psiElement, PsiMethod.class); + PsiMethod method = PsiTreeUtil.getParentOfType(psiElement, PsiMethod.class, true, PsiLambdaExpression.class); if (method != null && PsiType.VOID.equals(method.getReturnType())) { PsiReturnStatement stmt = (PsiReturnStatement)psiElement; if (stmt.getReturnValue() != null) { diff --git a/java/java-tests/testData/codeInsight/completeStatement/ReturnInLambda.java b/java/java-tests/testData/codeInsight/completeStatement/ReturnInLambda.java new file mode 100644 index 000000000000..2b5c63e7b53a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/ReturnInLambda.java @@ -0,0 +1,15 @@ +public class Class1 { + interface Lamb { + Object call(Object... args); + } + + public void m(Lamb l) { + + } + + public static void main(String[] args) { + new Ex().m((arg) -> { + return "" + }); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completeStatement/ReturnInLambda_after.java b/java/java-tests/testData/codeInsight/completeStatement/ReturnInLambda_after.java new file mode 100644 index 000000000000..c3d7d9a2f83e --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/ReturnInLambda_after.java @@ -0,0 +1,15 @@ +public class Class1 { + interface Lamb { + Object call(Object... args); + } + + public void m(Lamb l) { + + } + + public static void main(String[] args) { + new Ex().m((arg) -> { + return ""; + }); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/ImplementViaOverrideCompletion.java b/java/java-tests/testData/codeInsight/completion/normal/ImplementViaOverrideCompletion.java new file mode 100644 index 000000000000..588219546234 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ImplementViaOverrideCompletion.java @@ -0,0 +1,7 @@ +interface Foo { + void run(T t, int myInt); +} + +public class A implements Foo { + @Overr +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/ImplementViaOverrideCompletion_after.java b/java/java-tests/testData/codeInsight/completion/normal/ImplementViaOverrideCompletion_after.java new file mode 100644 index 000000000000..82ba62f6edd8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ImplementViaOverrideCompletion_after.java @@ -0,0 +1,10 @@ +interface Foo { + void run(T t, int myInt); +} + +public class A implements Foo { + @Override + public void run(String s, int myInt) { + + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java index 3f199d44ea13..927c8df52cf7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java @@ -270,6 +270,8 @@ public class CompleteStatementTest extends EditorActionTestCase { public void testArrayInitializerRBracket() throws Exception { doTest(); } + public void testReturnInLambda() { doTest(); } + private void doTestBracesNextLineStyle() throws Exception { CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); settings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE; diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index f65bff871ecf..f6d8b75a6719 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1355,6 +1355,14 @@ class XInternalError {} checkResult() } + public void testImplementViaOverrideCompletion() { + configure() + myFixture.assertPreferredCompletionItems 0, 'Override', 'public void run' + lookup.currentItem = lookup.items[1] + myFixture.type('\n') + checkResult() + } + public void testAccessorViaCompletion() { configure() diff --git a/platform/platform-impl/src/com/intellij/diagnostic/AbstractMessage.java b/platform/platform-impl/src/com/intellij/diagnostic/AbstractMessage.java index 16725a6022cf..82f67b71c6cb 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/AbstractMessage.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/AbstractMessage.java @@ -16,10 +16,14 @@ package com.intellij.diagnostic; import com.intellij.notification.Notification; +import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.SubmittedReportInfo; +import org.jetbrains.annotations.NotNull; import java.util.Calendar; +import java.util.Collections; import java.util.Date; +import java.util.List; public abstract class AbstractMessage { @@ -98,4 +102,9 @@ public abstract class AbstractMessage { public void setAssigneeId(Integer assigneeId) { myAssigneeId = assigneeId; } + + @NotNull + public List getAttachments() { + return Collections.emptyList(); + } } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/GroupedLogMessage.java b/platform/platform-impl/src/com/intellij/diagnostic/GroupedLogMessage.java index 80ed37aade57..d2709d9bd164 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/GroupedLogMessage.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/GroupedLogMessage.java @@ -15,6 +15,12 @@ */ package com.intellij.diagnostic; +import com.intellij.openapi.diagnostic.Attachment; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; import java.util.List; public class GroupedLogMessage extends AbstractMessage { @@ -60,4 +66,15 @@ public class GroupedLogMessage extends AbstractMessage { } super.setAssigneeId(assigneeId); } + + @NotNull + @Override + public List getAttachments() { + return ContainerUtil.concat(getMessages(), new Function>() { + @Override + public Collection fun(AbstractMessage message) { + return message.getAttachments(); + } + }); + } } diff --git a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java index b951b59ed9dd..92eb490fbb7c 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java @@ -111,9 +111,7 @@ public class ITNReporter extends ErrorReportSubmitter { Object data = event.getData(); if (data instanceof AbstractMessage) { errorBean.setAssigneeId(((AbstractMessage)data).getAssigneeId()); - } - if (data instanceof LogMessageEx) { - errorBean.setAttachments(((LogMessageEx)data).getAttachments()); + errorBean.setAttachments(((AbstractMessage)data).getAttachments()); } String login = settings.ITN_LOGIN; diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java index 88201f6b1738..9b4d66357957 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java @@ -468,13 +468,12 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene } private void updateAttachmentWarning(final AbstractMessage message) { - final List includedAttachments; - if (message instanceof LogMessageEx && - !(includedAttachments = ContainerUtil.filter(((LogMessageEx)message).getAttachments(), new Condition() { - public boolean value(final Attachment attachment) { - return attachment.isIncluded(); - } - })).isEmpty()) { + final List includedAttachments = ContainerUtil.filter(message.getAttachments(), new Condition() { + public boolean value(final Attachment attachment) { + return attachment.isIncluded(); + } + }); + if (!includedAttachments.isEmpty()) { myAttachmentWarningPanel.setVisible(true); if (includedAttachments.size() == 1) { myAttachmentWarningLabel.setHtmlText( @@ -649,7 +648,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene boolean hasAttachment = false; for (ArrayList merged : myMergedMessages) { final AbstractMessage message = merged.get(0); - if (message instanceof LogMessageEx && !((LogMessageEx)message).getAttachments().isEmpty()) { + if (!message.getAttachments().isEmpty()) { hasAttachment = true; break; } @@ -693,8 +692,7 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene myDetailsTabForm.setAssigneeId(message == null ? null : message.getAssigneeId()); - List attachments = - message instanceof LogMessageEx ? ((LogMessageEx)message).getAttachments() : Collections.emptyList(); + List attachments = message != null ? message.getAttachments() : Collections.emptyList(); if (!attachments.isEmpty()) { if (myTabs.indexOfComponent(myAttachmentsTabForm.getContentPane()) == -1) { myTabs.addTab(DiagnosticBundle.message("error.attachments.tab.title"), myAttachmentsTabForm.getContentPane()); diff --git a/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java b/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java index ada03a4f3330..ad7f148b6947 100644 --- a/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java +++ b/platform/platform-impl/src/com/intellij/diagnostic/LogMessageEx.java @@ -76,6 +76,8 @@ public class LogMessageEx extends LogMessage { myAttachments.add(attachment); } + @NotNull + @Override public List getAttachments() { return myAttachments != null ? myAttachments : Collections.emptyList(); }