Merge remote branch 'origin/master'

This commit is contained in:
Alex Tkachman
2011-12-12 13:22:03 +02:00
10 changed files with 188 additions and 6 deletions
@@ -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;
}
}