Merge remote branch 'origin/master'
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jet.plugin.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.patterns.PsiElementPattern;
|
||||
@@ -11,6 +12,7 @@ import com.intellij.psi.filters.position.FilterPattern;
|
||||
import com.intellij.psi.filters.position.LeftNeighbour;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.plugin.completion.handlers.JetKeywordInsertHandler;
|
||||
|
||||
/**
|
||||
* A keyword contributor for Kotlin
|
||||
@@ -21,7 +23,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class JetKeywordCompletionContributor extends CompletionContributor {
|
||||
|
||||
private static class JetTopKeywordCompletionProvider extends CompletionProvider<CompletionParameters> {
|
||||
|
||||
|
||||
private final static InsertHandler<LookupElement> KEYWORDS_INSERT_HANDLER = new JetKeywordInsertHandler();
|
||||
|
||||
private final static String[] COMPLETE_KEYWORD = new String[] {
|
||||
"namespace", "as", "type", "class", "this", "super", "val", "var", "fun", "for", "null", "true",
|
||||
"false", "is", "in", "throw", "return", "break", "continue", "object", "if", "try", "else", "while",
|
||||
@@ -32,18 +36,19 @@ public class JetKeywordCompletionContributor extends CompletionContributor {
|
||||
"import", "where", "by", "get", "set", "abstract", "enum", "open", "annotation", "override", "private",
|
||||
"public", "internal", "protected", "catch", "out", "vararg", "inline", "finally", "final", "ref"
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
ProcessingContext context,
|
||||
@NotNull CompletionResultSet result) {
|
||||
|
||||
for (String keyword : COMPLETE_KEYWORD) {
|
||||
result.addElement(LookupElementBuilder.create(keyword).setBold());
|
||||
|
||||
result.addElement(LookupElementBuilder.create(keyword).setInsertHandler(KEYWORDS_INSERT_HANDLER).setBold());
|
||||
}
|
||||
|
||||
for (String softKeyword : COMPLETE_SOFT_KEYWORDS) {
|
||||
result.addElement(LookupElementBuilder.create(softKeyword));
|
||||
result.addElement(LookupElementBuilder.create(softKeyword).setInsertHandler(KEYWORDS_INSERT_HANDLER));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package org.jetbrains.jet.plugin.completion.handlers;
|
||||
|
||||
import com.intellij.codeInsight.completion.InsertHandler;
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
|
||||
/**
|
||||
* Inserts '()' after function proposal insert.
|
||||
*
|
||||
* @author Nikolay Krasko
|
||||
*/
|
||||
public class JetFunctionInsertHandler implements InsertHandler<LookupElement> {
|
||||
|
||||
public enum CaretPosition { IN_BRACKETS, AFTER_BRACKETS }
|
||||
|
||||
private final CaretPosition caretPosition;
|
||||
|
||||
public JetFunctionInsertHandler(CaretPosition caretPosition) {
|
||||
this.caretPosition = caretPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||
int startOffset = context.getStartOffset();
|
||||
int lookupStringLength = item.getLookupString().length();
|
||||
int endOffset = startOffset + lookupStringLength;
|
||||
|
||||
context.getDocument().insertString(endOffset, "()");
|
||||
|
||||
Editor editor = context.getEditor();
|
||||
if (caretPosition == CaretPosition.IN_BRACKETS) {
|
||||
editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 1);
|
||||
} else {
|
||||
editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.jetbrains.jet.plugin.completion.handlers;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.codeInsight.completion.InsertHandler;
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Nikolay Krasko
|
||||
*/
|
||||
public class JetKeywordInsertHandler implements InsertHandler<LookupElement> {
|
||||
|
||||
private final static Set<String> NO_SPACE_AFTER = Sets.newHashSet("this", "super", "This", "true", "false", "null");
|
||||
|
||||
@Override
|
||||
public void handleInsert(InsertionContext context, LookupElement item) {
|
||||
String keyword = item.getLookupString();
|
||||
|
||||
// Add space after keyword
|
||||
if (!NO_SPACE_AFTER.contains(keyword)) {
|
||||
Editor editor = context.getEditor();
|
||||
Document document = editor.getDocument();
|
||||
|
||||
int offset = context.getStartOffset() + keyword.length();
|
||||
context.setAddCompletionChar(false);
|
||||
document.insertString(offset, " ");
|
||||
editor.getCaretModel().moveToOffset(editor.getCaretModel().getOffset() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.Variance;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
import org.jetbrains.jet.plugin.completion.handlers.JetFunctionInsertHandler;
|
||||
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||
|
||||
import java.util.List;
|
||||
@@ -37,6 +38,13 @@ import java.util.Set;
|
||||
* @author yole
|
||||
*/
|
||||
class JetSimpleNameReference extends JetPsiReference {
|
||||
|
||||
private final static JetFunctionInsertHandler EMPTY_FUNCTION_HANDLER = new JetFunctionInsertHandler(
|
||||
JetFunctionInsertHandler.CaretPosition.AFTER_BRACKETS);
|
||||
|
||||
private final static JetFunctionInsertHandler PARAMS_FUNCTION_HANDLER = new JetFunctionInsertHandler(
|
||||
JetFunctionInsertHandler.CaretPosition.IN_BRACKETS);
|
||||
|
||||
private final JetSimpleNameExpression myExpression;
|
||||
|
||||
public JetSimpleNameReference(JetSimpleNameExpression jetSimpleNameExpression) {
|
||||
@@ -135,10 +143,12 @@ class JetSimpleNameReference extends JetPsiReference {
|
||||
String typeText = "";
|
||||
String tailText = "";
|
||||
boolean tailTextGrayed = false;
|
||||
|
||||
if (descriptor instanceof FunctionDescriptor) {
|
||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||
JetType returnType = functionDescriptor.getReturnType();
|
||||
typeText = DescriptorRenderer.TEXT.renderType(returnType);
|
||||
|
||||
tailText = "(" + StringUtil.join(functionDescriptor.getValueParameters(), new Function<ValueParameterDescriptor, String>() {
|
||||
@Override
|
||||
public String fun(ValueParameterDescriptor valueParameterDescriptor) {
|
||||
@@ -146,6 +156,14 @@ class JetSimpleNameReference extends JetPsiReference {
|
||||
DescriptorRenderer.TEXT.renderType(valueParameterDescriptor.getOutType());
|
||||
}
|
||||
}, ",") + ")";
|
||||
|
||||
// TODO: A special case when it's impossible to resolve type parameters from arguments. Need '<' caret '>'
|
||||
// TODO: Support omitting brackets for one argument functions
|
||||
if (functionDescriptor.getValueParameters().isEmpty()) {
|
||||
element = element.setInsertHandler(EMPTY_FUNCTION_HANDLER);
|
||||
} else {
|
||||
element = element.setInsertHandler(PARAMS_FUNCTION_HANDLER);
|
||||
}
|
||||
}
|
||||
else if (descriptor instanceof VariableDescriptor) {
|
||||
JetType outType = ((VariableDescriptor) descriptor).getOutType();
|
||||
@@ -170,8 +188,8 @@ class JetSimpleNameReference extends JetPsiReference {
|
||||
return result.toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that receiver declaration could be resolved to call expected receiver.
|
||||
/*
|
||||
* Checks if receiver declaration could be resolved to call expected receiver.
|
||||
*/
|
||||
private static boolean checkReceiverResolution (
|
||||
@NotNull ReceiverDescriptor expectedReceiver,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fun test() {
|
||||
}
|
||||
|
||||
fun other() {
|
||||
te<caret>
|
||||
}
|
||||
|
||||
// INSERT: test
|
||||
@@ -0,0 +1,8 @@
|
||||
fun test() {
|
||||
}
|
||||
|
||||
fun other() {
|
||||
test()<caret>
|
||||
}
|
||||
|
||||
// INSERT: test
|
||||
@@ -0,0 +1,6 @@
|
||||
fun test(a: Int) {
|
||||
}
|
||||
|
||||
fun other() {
|
||||
te<caret>
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
fun test(a: Int) {
|
||||
}
|
||||
|
||||
fun other() {
|
||||
test(<caret>)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.jetbrains.jet.completion.handlers;
|
||||
|
||||
import com.intellij.codeInsight.completion.LightCompletionTestCase;
|
||||
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Nikolay Krasko
|
||||
*/
|
||||
public class FunctionsHandlerTest extends LightCompletionTestCase {
|
||||
|
||||
public void testNoParamsFunction() {
|
||||
configureByFile("NoParamsFunction.kt");
|
||||
checkResultByFile("NoParamsFunction.kt.after");
|
||||
}
|
||||
|
||||
public void testFunctionWithParams() {
|
||||
configureByFile("ParamsFunction.kt");
|
||||
checkResultByFile("ParamsFunction.kt.after");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() +
|
||||
File.separator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.jetbrains.jet.completion.handlers;
|
||||
|
||||
import com.intellij.codeInsight.completion.LightCompletionTestCase;
|
||||
import org.jetbrains.jet.plugin.PluginTestCaseBase;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author Nikolay Krasko
|
||||
*/
|
||||
public class KeywordsHandlerTest extends LightCompletionTestCase {
|
||||
|
||||
public void testSpaceAfter() throws IOException {
|
||||
configureFromFileText("Test.kt", "protecte<caret>");
|
||||
complete();
|
||||
checkResultByText("protected <caret>");
|
||||
}
|
||||
|
||||
public void testNoSpaceAfter() throws IOException {
|
||||
configureFromFileText("Test.kt", "nul<caret>");
|
||||
complete();
|
||||
checkResultByText("null<caret>");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getTestDataPath() {
|
||||
return new File(PluginTestCaseBase.getTestDataPathBase(), "/completion/handlers/").getPath() +
|
||||
File.separator;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user