diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java index fe7575b1766..dee80681d3d 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java @@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.plugin.JetDescriptorIconProvider; import org.jetbrains.jet.plugin.completion.handlers.JetClassInsertHandler; import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler; @@ -41,10 +42,13 @@ import java.util.List; public final class DescriptorLookupConverter { private final static JetFunctionInsertHandler EMPTY_FUNCTION_HANDLER = new JetFunctionInsertHandler( - JetFunctionInsertHandler.CaretPosition.AFTER_BRACKETS); + JetFunctionInsertHandler.CaretPosition.AFTER_BRACKETS, JetFunctionInsertHandler.BracketType.PARENTHESIS); - private final static JetFunctionInsertHandler PARAMS_FUNCTION_HANDLER = new JetFunctionInsertHandler( - JetFunctionInsertHandler.CaretPosition.IN_BRACKETS); + private final static JetFunctionInsertHandler PARAMS_PARENTHESIS_FUNCTION_HANDLER = new JetFunctionInsertHandler( + JetFunctionInsertHandler.CaretPosition.IN_BRACKETS, JetFunctionInsertHandler.BracketType.PARENTHESIS); + + private final static JetFunctionInsertHandler PARAMS_BRACES_FUNCTION_HANDLER = new JetFunctionInsertHandler( + JetFunctionInsertHandler.CaretPosition.IN_BRACKETS, JetFunctionInsertHandler.BracketType.BRACES); private DescriptorLookupConverter() {} @@ -79,7 +83,12 @@ public final class DescriptorLookupConverter { element = element.setInsertHandler(EMPTY_FUNCTION_HANDLER); } else { - element = element.setInsertHandler(PARAMS_FUNCTION_HANDLER); + if (functionDescriptor.getValueParameters().size() == 1 + && JetStandardClasses.isFunctionType(functionDescriptor.getValueParameters().get(0).getType())) { + element = element.setInsertHandler(PARAMS_BRACES_FUNCTION_HANDLER); + } else { + element = element.setInsertHandler(PARAMS_PARENTHESIS_FUNCTION_HANDLER); + } } } else if (descriptor instanceof VariableDescriptor) { diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java index 63e98a5058d..fa8cc613c9c 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetKeywordCompletionContributor.java @@ -56,7 +56,7 @@ public class JetKeywordCompletionContributor extends CompletionContributor { private final static InsertHandler KEYWORDS_INSERT_HANDLER = new JetKeywordInsertHandler(); private final static InsertHandler FUNCTION_INSERT_HANDLER = new JetFunctionInsertHandler( - JetFunctionInsertHandler.CaretPosition.AFTER_BRACKETS); + JetFunctionInsertHandler.CaretPosition.AFTER_BRACKETS, JetFunctionInsertHandler.BracketType.PARENTHESIS); private final static ElementFilter GENERAL_FILTER = new NotFilter(new OrFilter( new CommentFilter(), // or diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java index 03554a4de9b..50ad3510465 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetFunctionInsertHandler.java @@ -47,11 +47,14 @@ import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper; public class JetFunctionInsertHandler implements InsertHandler { public enum CaretPosition { IN_BRACKETS, AFTER_BRACKETS } + public enum BracketType { PARENTHESIS, BRACES } private final CaretPosition caretPosition; + private final BracketType bracketType; - public JetFunctionInsertHandler(CaretPosition caretPosition) { + public JetFunctionInsertHandler(CaretPosition caretPosition, BracketType bracketType) { this.caretPosition = caretPosition; + this.bracketType = bracketType; } @Override @@ -87,22 +90,36 @@ public class JetFunctionInsertHandler implements InsertHandler { boolean bothParentheses = false; String documentText = document.getText(); - if (!(endOffset < documentText.length() && documentText.charAt(endOffset) == '(')) { - // Insert () if it's not already exist - document.insertString(endOffset, "()"); + boolean braces = bracketType == BracketType.BRACES && context.getCompletionChar() != '('; + char openingBracket = braces ? '{' : '('; + char closingBracket = braces ? '}' : ')'; + int openingBracketIndex = documentText.indexOf(openingBracket, endOffset); + if (openingBracketIndex != -1 && documentText.substring(endOffset, openingBracketIndex).trim().length() != 0) { + openingBracketIndex = -1; // opening bracket is too far + } + if (openingBracketIndex == -1) { + // Insert ()/{} if it's not already exist + if (braces) { + document.insertString(endOffset, " {}"); + openingBracketIndex = endOffset + 1; + } + else { + document.insertString(endOffset, "()"); + openingBracketIndex = endOffset; + } bothParentheses = true; } - else if (endOffset + 1 < documentText.length() && documentText.charAt(endOffset + 1) == ')') { + else if (openingBracketIndex + 1 < documentText.length() && documentText.charAt(openingBracketIndex + 1) == closingBracket) { bothParentheses = true; } Editor editor = context.getEditor(); if (caretPosition == CaretPosition.IN_BRACKETS || !bothParentheses) { - editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 1); + editor.getCaretModel().moveToOffset(openingBracketIndex + 1); AutoPopupController.getInstance(context.getProject()).autoPopupParameterInfo(editor, offsetElement); } else { - editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 2); + editor.getCaretModel().moveToOffset(openingBracketIndex + 2); } PsiDocumentManager.getInstance(context.getProject()).commitDocument(context.getDocument()); diff --git a/idea/testData/completion/handlers/HigherOrderFunction.kt b/idea/testData/completion/handlers/HigherOrderFunction.kt new file mode 100644 index 00000000000..dc92137c7c7 --- /dev/null +++ b/idea/testData/completion/handlers/HigherOrderFunction.kt @@ -0,0 +1,5 @@ +fun jet.Array.filter(predicate : (T) -> jet.Boolean) : java.util.List = throw UnsupportedOperationException() + +fun main(args: Array) { + args.fil +} diff --git a/idea/testData/completion/handlers/HigherOrderFunction.kt.after b/idea/testData/completion/handlers/HigherOrderFunction.kt.after new file mode 100644 index 00000000000..83984db0e82 --- /dev/null +++ b/idea/testData/completion/handlers/HigherOrderFunction.kt.after @@ -0,0 +1,5 @@ +fun jet.Array.filter(predicate : (T) -> jet.Boolean) : java.util.List = throw UnsupportedOperationException() + +fun main(args: Array) { + args.filter {} +} diff --git a/idea/testData/completion/handlers/HigherOrderFunctionWithArg.kt b/idea/testData/completion/handlers/HigherOrderFunctionWithArg.kt new file mode 100644 index 00000000000..1eee74adb67 --- /dev/null +++ b/idea/testData/completion/handlers/HigherOrderFunctionWithArg.kt @@ -0,0 +1,7 @@ +fun jet.Array.filter(predicate : (T) -> jet.Boolean) : java.util.List = throw UnsupportedOperationException() + +fun jet.Array.filterNot(predicate : (T) -> jet.Boolean) : java.util.List = throw UnsupportedOperationException() + +fun main(args: Array) { + args.filter {it != ""} +} diff --git a/idea/testData/completion/handlers/HigherOrderFunctionWithArg.kt.after b/idea/testData/completion/handlers/HigherOrderFunctionWithArg.kt.after new file mode 100644 index 00000000000..2e96d9cfb8a --- /dev/null +++ b/idea/testData/completion/handlers/HigherOrderFunctionWithArg.kt.after @@ -0,0 +1,7 @@ +fun jet.Array.filter(predicate : (T) -> jet.Boolean) : java.util.List = throw UnsupportedOperationException() + +fun jet.Array.filterNot(predicate : (T) -> jet.Boolean) : java.util.List = throw UnsupportedOperationException() + +fun main(args: Array) { + args.filterNot {it != ""} +} diff --git a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTest.java b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTest.java index 534538c504e..f8cf2dfc385 100644 --- a/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTest.java +++ b/idea/tests/org/jetbrains/jet/completion/handlers/CompletionHandlerTest.java @@ -72,6 +72,14 @@ public class CompletionHandlerTest extends LightCompletionTestCase { doTest(); } + public void testHigherOrderFunction() { + doTest(); + } + + public void testHigherOrderFunctionWithArg() { + doTest(CompletionType.BASIC, 2, "filterNot", null); + } + public void doTest() { doTest(CompletionType.BASIC, 2, null, null); }