Merge remote-tracking branch 'origin/master'

This commit is contained in:
svtk
2011-12-08 13:43:56 +04:00
80 changed files with 2197 additions and 498 deletions
@@ -4,7 +4,7 @@ import com.intellij.ide.IconProvider;
import com.intellij.openapi.util.Iconable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Icons;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lexer.JetTokens;
@@ -15,21 +15,21 @@ import javax.swing.*;
* @author yole
*/
public class JetIconProvider extends IconProvider {
public static final Icon ICON_FOR_OBJECT = Icons.ANONYMOUS_CLASS_ICON;
public static final Icon ICON_FOR_OBJECT = PlatformIcons.ANONYMOUS_CLASS_ICON;
@Override
public Icon getIcon(@NotNull PsiElement psiElement, int flags) {
if (psiElement instanceof JetNamespace) {
return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? Icons.PACKAGE_OPEN_ICON : Icons.PACKAGE_ICON;
return (flags & Iconable.ICON_FLAG_OPEN) != 0 ? PlatformIcons.PACKAGE_OPEN_ICON : PlatformIcons.PACKAGE_ICON;
}
if (psiElement instanceof JetNamedFunction) {
return PsiTreeUtil.getParentOfType(psiElement, JetNamedDeclaration.class) instanceof JetClass
? Icons.METHOD_ICON
: Icons.FUNCTION_ICON;
? PlatformIcons.METHOD_ICON
: PlatformIcons.FUNCTION_ICON;
}
if (psiElement instanceof JetClass) {
JetClass jetClass = (JetClass) psiElement;
Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? Icons.ENUM_ICON : Icons.CLASS_ICON;
Icon icon = jetClass.hasModifier(JetTokens.ENUM_KEYWORD) ? PlatformIcons.ENUM_ICON : PlatformIcons.CLASS_ICON;
if (jetClass instanceof JetEnumEntry) {
JetEnumEntry enumEntry = (JetEnumEntry) jetClass;
if (enumEntry.getPrimaryConstructorParameterList() == null) {
@@ -42,13 +42,13 @@ public class JetIconProvider extends IconProvider {
if (((JetParameter) psiElement).getValOrVarNode() != null) {
JetParameterList parameterList = PsiTreeUtil.getParentOfType(psiElement, JetParameterList.class);
if (parameterList != null && parameterList.getParent() instanceof JetClass) {
return Icons.PROPERTY_ICON;
return PlatformIcons.PROPERTY_ICON;
}
}
return Icons.PARAMETER_ICON;
return PlatformIcons.PARAMETER_ICON;
}
if (psiElement instanceof JetProperty) {
return Icons.PROPERTY_ICON;
return PlatformIcons.PROPERTY_ICON;
}
return null;
}
@@ -24,13 +24,23 @@ import java.util.Set;
/**
* @author abreslav
*/
public class WholeProjectAnalyzerFacade {
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetDeclaration>>() {
public final class WholeProjectAnalyzerFacade {
/** Forbid creating */
private WholeProjectAnalyzerFacade() {}
/**
* Will collect all root-namespaces in all kotlin files in the project.
*/
public static final Function<JetFile, Collection<JetDeclaration>> WHOLE_PROJECT_DECLARATION_PROVIDER =
new Function<JetFile, Collection<JetDeclaration>>() {
@Override
public Collection<JetDeclaration> fun(final JetFile rootFile) {
final Project project = rootFile.getProject();
final Set<JetDeclaration> namespaces = Sets.newLinkedHashSet();
ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
final ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
if (rootManager != null && !ApplicationManager.getApplication().isUnitTestMode()) {
VirtualFile[] contentRoots = rootManager.getContentRoots();
@@ -55,9 +65,9 @@ public class WholeProjectAnalyzerFacade {
}
};
@NotNull
public static BindingContext analyzeProjectWithCacheOnAFile(@NotNull JetFile file) {
return AnalyzerFacade.analyzeFileWithCache(file, WHOLE_PROJECT_DECLARATION_PROVIDER);
}
}
@@ -21,27 +21,31 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.content.ContentFactory;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.ResolvedValueArgument;
import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemImpl;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.plugin.JetFileType;
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
import org.jetbrains.jet.plugin.internal.codewindow.BytecodeToolwindow;
import org.jetbrains.jet.util.slicedmap.ReadOnlySlice;
import org.jetbrains.jet.util.slicedmap.WritableSlice;
import javax.swing.*;
import java.awt.*;
import java.util.Map;
import static org.jetbrains.jet.lang.resolve.BindingContext.EXPRESSION_TYPE;
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
import static org.jetbrains.jet.lang.resolve.BindingContext.RESOLVED_CALL;
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
import static org.jetbrains.jet.lang.resolve.calls.ResolutionDebugInfo.*;
/*
* @author abreslav
@@ -121,19 +125,20 @@ public class ResolveToolwindow extends JPanel {
PsiElement currentElement = elementAtOffset;
boolean callFound = false;
while (currentElement != null && !(currentElement instanceof PsiFile)) {
if (currentElement instanceof JetElement) {
JetElement atOffset = (JetElement) currentElement;
ResolvedCall<? extends CallableDescriptor> resolvedCall = bindingContext.get(RESOLVED_CALL, (JetElement) atOffset);
if (resolvedCall != null) {
setText(renderCall(resolvedCall) + "\n===\n" + currentElement + ": " + currentElement.getText());
callFound = true;
break;
}
}
currentElement = currentElement.getParent();
PsiElement elementWithDebugInfo = findData(bindingContext, currentElement, RESOLUTION_DEBUG_INFO);
if (elementWithDebugInfo != null) {
callFound = true;
setText(renderDebugInfo(elementWithDebugInfo, bindingContext.get(RESOLUTION_DEBUG_INFO, elementWithDebugInfo), null));
}
else {
PsiElement elementWithResolvedCall = findData(bindingContext, currentElement, (WritableSlice) RESOLVED_CALL);
if (elementWithResolvedCall instanceof JetElement) {
callFound = true;
setText(renderDebugInfo(elementWithResolvedCall, null, bindingContext.get(RESOLVED_CALL, (JetElement) elementWithResolvedCall)));
}
}
if (!callFound) {
JetExpression parentExpression = (elementAtOffset instanceof JetExpression) ? (JetExpression) elementAtOffset
@@ -153,8 +158,70 @@ public class ResolveToolwindow extends JPanel {
}
}
private String renderCall(ResolvedCall<? extends CallableDescriptor> resolvedCall) {
StringBuilder builder = new StringBuilder();
@Nullable
private <D> PsiElement findData(BindingContext bindingContext, PsiElement currentElement, ReadOnlySlice<PsiElement, D> slice) {
while (currentElement != null && !(currentElement instanceof PsiFile)) {
if (currentElement instanceof JetElement) {
JetElement atOffset = (JetElement) currentElement;
D data = bindingContext.get(slice, atOffset);
if (data != null && data != NO_DEBUG_INFO) {
return currentElement;
}
}
currentElement = currentElement.getParent();
}
return null;
}
private String renderDebugInfo(PsiElement currentElement, @Nullable ResolutionDebugInfo.Data debugInfo, @Nullable ResolvedCall<? extends CallableDescriptor> call) {
final String bar = "\n\n===\n\n";
StringBuilder result = new StringBuilder();
if (debugInfo != null) {
StringBuilder errors = debugInfo.get(ERRORS);
if (errors != null) {
result.append("Errors: \n").append(errors).append(bar);
}
StringBuilder log = debugInfo.get(LOG);
if (log != null) {
result.append("Log: \n").append(log).append(bar);
}
Map<JetType, ConstraintSystemImpl.TypeValue> knowns = debugInfo.get(BOUNDS_FOR_KNOWNS);
renderMap(knowns, result);
Map<TypeParameterDescriptor, ConstraintSystemImpl.TypeValue> unknowns = debugInfo.get(BOUNDS_FOR_UNKNOWNS);
renderMap(unknowns, result);
result.append(bar);
call = debugInfo.get(RESULT);
}
renderCall(result, call);
result.append(currentElement + ": " + currentElement.getText());
return result.toString();
}
private <K> void renderMap(Map<K, ConstraintSystemImpl.TypeValue> map, StringBuilder builder) {
if (map == null) return;
for (Map.Entry<K, ConstraintSystemImpl.TypeValue> entry : map.entrySet()) {
K key = entry.getKey();
ConstraintSystemImpl.TypeValue typeValue = entry.getValue();
builder.append("Bounds for ").append(key).append("\n");
for (ConstraintSystemImpl.TypeValue bound : typeValue.getLowerBounds()) {
builder.append(" >: ").append(bound).append("\n");
}
for (ConstraintSystemImpl.TypeValue bound : typeValue.getUpperBounds()) {
builder.append(" <: ").append(bound).append("\n");
}
}
}
private String renderCall(StringBuilder builder, ResolvedCall<? extends CallableDescriptor> resolvedCall) {
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
ReceiverDescriptor receiverArgument = resolvedCall.getReceiverArgument();
@@ -0,0 +1,9 @@
namespace Tests
import java.util.*
fun hello() {
val a = So<caret>
}
// EXIST: SortedSet, SortedMap
@@ -0,0 +1,6 @@
namespace Tests
class A : java.<caret>
// EXIST: lang, util, io
// ABSENT: fun, val, var, namespace
@@ -1,10 +1,10 @@
open class MyClass() {
}
class A() : My<caret> {
class A() {
public fun test() {
val a : MyC<caret>
}
}
// EXIST: MyClass
// EXIST: MyClass
@@ -3,4 +3,4 @@ fun foo() {
}
// TODO: Move all keywords to absent
// EXPECT: fun, val, var, namespace
// EXIST: fun, val, var, namespace
@@ -1,8 +1,8 @@
<caret>
// EXPECT: namespace, as, type, class, this, super, val, var, fun, for, null, true
// EXPECT: false, is, in, throw, return, break, continue, object, if, try, else, while
// EXPECT: do, when, trait, This
// EXPECT: import, where, by, get, set, abstract, enum, open, annotation, override, private
// EXPECT: public, internal, protected, catch, out, vararg, inline, finally, final, ref
// EXIST: namespace, as, type, class, this, super, val, var, fun, for, null, true
// EXIST: false, is, in, throw, return, break, continue, object, if, try, else, while
// EXIST: do, when, trait, This
// EXIST: import, where, by, get, set, abstract, enum, open, annotation, override, private
// EXIST: public, internal, protected, catch, out, vararg, inline, finally, final, ref
// ABSENT: ?in, new, extends, implements
@@ -23,7 +23,7 @@ public class JetBasicCompletionTest extends JetCompletionTestBase {
setName("testCompletionExecute");
}
public void testCompletionExecute() {
public void testCompletionExecute() throws Exception {
doTest();
}
@@ -2,70 +2,64 @@ package org.jetbrains.jet.completion;
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.LightCompletionTestCase;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupEx;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.plugin.PluginTestCaseBase;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
* @author Nikolay.Krasko
*/
public abstract class JetCompletionTestBase extends LightCodeInsightTestCase {
public abstract class JetCompletionTestBase extends LightCompletionTestCase {
protected void doTest() {
private CompletionType type;
protected void doTest() throws Exception {
final String testName = getTestName(false);
type = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
configureByFile(testName + ".kt");
CompletionType completionType = (testName.startsWith("Smart")) ? CompletionType.SMART : CompletionType.BASIC;
new CodeCompletionHandlerBase(completionType, false, false, true).invokeCompletion(getProject(), getEditor());
LookupEx lookup = LookupManager.getActiveLookup(getEditor());
assert lookup != null;
HashSet<String> items = new HashSet<String>(resolveLookups(lookup.getItems()));
List<String> shouldExist = itemsShouldExist(getFile().getText());
for (String shouldExistItem : shouldExist) {
assertTrue(String.format("Should contain proposal '%s'.", shouldExistItem),
items.contains(shouldExistItem));
}
List<String> shouldAbsent = itemsShouldAbsent(getFile().getText());
for (String shouldAbsentItem : shouldAbsent) {
assertTrue(String.format("Shouldn't contain proposal '%s'.", shouldAbsentItem),
!items.contains(shouldAbsentItem));
}
assertContainsItems(itemsShouldExist(getFile().getText()));
assertNotContainItems(itemsShouldAbsent(getFile().getText()));
}
private static List<String> resolveLookups(List<LookupElement> items) {
ArrayList<String> result = new ArrayList<String>(items.size());
for (LookupElement item : items) {
result.add(item.getLookupString());
}
return result;
@Override
protected Sdk getProjectJDK() {
return PluginTestCaseBase.jdkFromIdeaHome();
}
@Override
protected void complete(final int time) {
new CodeCompletionHandlerBase(type, false, false, true).invokeCompletion(getProject(), getEditor(), time, false);
LookupImpl lookup = (LookupImpl) LookupManager.getActiveLookup(myEditor);
myItems = lookup == null ? null : lookup.getItems().toArray(LookupElement.EMPTY_ARRAY);
myPrefix = lookup == null ? null : lookup.itemPattern(lookup.getItems().get(0));
}
@NotNull
private static List<String> itemsShouldExist(String fileText) {
private static String[] itemsShouldExist(String fileText) {
return findListWithPrefix("// EXIST:", fileText);
}
@NotNull
private static List<String> itemsShouldAbsent(String fileText) {
private static String[] itemsShouldAbsent(String fileText) {
return findListWithPrefix("// ABSENT:", fileText);
}
@NotNull
private static List<String> findListWithPrefix(String prefix, String fileText) {
private static String[] findListWithPrefix(String prefix, String fileText) {
ArrayList<String> result = new ArrayList<String>();
for (String line : findLinesWithPrefixRemoved(prefix, fileText)) {
@@ -76,7 +70,7 @@ public abstract class JetCompletionTestBase extends LightCodeInsightTestCase {
}
}
return result;
return result.toArray(new String[result.size()]);
}
@NotNull
@@ -1,5 +1,6 @@
package org.jetbrains.jet.completion;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBuilder;
@@ -25,7 +26,7 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
setName("testCompletionExecute");
}
public void testCompletionExecute() {
public void testCompletionExecute() throws Exception {
doTest();
}
@@ -49,13 +50,14 @@ public class KeywordsCompletionTest extends JetCompletionTestBase {
PluginTestCaseBase.getTestDataPathBase(), "/completion/keywords/", false,
JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull
@Override
public junit.framework.Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
public Test createTest(@NotNull String dataPath, @NotNull String name, @NotNull File file) {
return new KeywordsCompletionTest(dataPath, name);
}
}, suite);
return suite;
}
}
}