Merge remote-tracking branch 'origin/master'

This commit is contained in:
pTalanov
2012-02-27 19:57:37 +04:00
68 changed files with 1350 additions and 310 deletions
@@ -124,7 +124,7 @@ public class CallableMethod implements Callable {
}
public boolean isNeedsThis() {
return thisClass != null;
return thisClass != null && generateCalleeType == null;
}
public boolean isNeedsReceiver() {
@@ -91,6 +91,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
if (fd.getReceiverParameter().exists()) {
result.setNeedsReceiver(fd);
}
result.setNeedsThis(getInternalType(fd));
result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
return result;
}
@@ -337,6 +338,16 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
}
}
public static ClassDescriptor getInternalType(FunctionDescriptor descriptor) {
final int paramCount = descriptor.getValueParameters().size();
if (descriptor.getReceiverParameter().exists()) {
return JetStandardClasses.getReceiverFunction(paramCount);
}
else {
return JetStandardClasses.getFunction(paramCount);
}
}
private void appendType(SignatureWriter signatureWriter, JetType type, char variance) {
signatureWriter.visitTypeArgument(variance);
@@ -431,6 +431,14 @@ public class FunctionCodegen {
private static void checkOverride(CodegenContext owner, GenerationState state, ClassBuilder v, Method jvmSignature, FunctionDescriptor functionDescriptor, FunctionDescriptor overriddenFunction) {
Method method = state.getTypeMapper().mapSignature(functionDescriptor.getName(), functionDescriptor).getAsmMethod();
Method overriden = state.getTypeMapper().mapSignature(overriddenFunction.getName(), overriddenFunction.getOriginal()).getAsmMethod();
if(overriddenFunction.getModality() == Modality.ABSTRACT) {
Set<? extends FunctionDescriptor> overriddenFunctions = overriddenFunction.getOverriddenDescriptors();
for (FunctionDescriptor of : overriddenFunctions) {
checkOverride(owner, state, v, jvmSignature, overriddenFunction, of.getOriginal());
}
}
if(differentMethods(method, overriden)) {
int flags = ACC_PUBLIC | ACC_BRIDGE; // TODO.
@@ -138,7 +138,7 @@ public interface JetNodeTypes {
JetNodeType DOT_QUALIFIED_EXPRESSION = new JetNodeType("DOT_QUALIFIED_EXPRESSION", JetDotQualifiedExpression.class);
JetNodeType HASH_QUALIFIED_EXPRESSION = new JetNodeType("HASH_QUALIFIED_EXPRESSION", JetHashQualifiedExpression.class);
JetNodeType SAFE_ACCESS_EXPRESSION = new JetNodeType("SAFE_ACCESS_EXPRESSION", JetSafeQualifiedExpression.class);
JetNodeType PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
// JetNodeType PREDICATE_EXPRESSION = new JetNodeType("PREDICATE_EXPRESSION", JetPredicateExpression.class);
JetNodeType OBJECT_LITERAL = new JetNodeType("OBJECT_LITERAL", JetObjectLiteralExpression.class);
JetNodeType ROOT_NAMESPACE = new JetNodeType("ROOT_NAMESPACE", JetRootNamespaceExpression.class);
@@ -385,13 +385,13 @@ public class JetExpressionParsing extends AbstractJetParsing {
expression.done(SAFE_ACCESS_EXPRESSION);
}
else if (at(QUEST)) {
advance(); // QUEST
parseCallExpression();
expression.done(PREDICATE_EXPRESSION);
}
// else if (at(QUEST)) {
// advance(); // QUEST
//
// parseCallExpression();
//
// expression.done(PREDICATE_EXPRESSION);
// }
// else if (at(HASH)) {
// advance(); // HASH
//
@@ -207,8 +207,12 @@ public class JetParsing extends AbstractJetParsing {
advance(); // DOT
reference = mark();
expect(IDENTIFIER, "Qualified name must be a '.'-separated identifier list", TokenSet.create(AS_KEYWORD, DOT, SEMICOLON));
reference.done(REFERENCE_EXPRESSION);
if (expect(IDENTIFIER, "Qualified name must be a '.'-separated identifier list", TokenSet.create(AS_KEYWORD, DOT, SEMICOLON))) {
reference.done(REFERENCE_EXPRESSION);
}
else {
reference.drop();
}
PsiBuilder.Marker precede = qualifiedName.precede();
qualifiedName.done(DOT_QUALIFIED_EXPRESSION);
@@ -817,7 +821,7 @@ public class JetParsing extends AbstractJetParsing {
errorAndAdvance("Expecting 'val' or 'var'");
}
boolean typeParametersDeclared = at(LT) ? parseTypeParameterList(TokenSet.create(IDENTIFIER, EQ, COLON, SEMICOLON)) : false;
boolean typeParametersDeclared = at(LT) && parseTypeParameterList(TokenSet.create(IDENTIFIER, EQ, COLON, SEMICOLON));
TokenSet propertyNameFollow = TokenSet.create(COLON, EQ, LBRACE, SEMICOLON, VAL_KEYWORD, VAR_KEYWORD, FUN_KEYWORD, CLASS_KEYWORD);
@@ -1236,8 +1240,11 @@ public class JetParsing extends AbstractJetParsing {
}
PsiBuilder.Marker reference = mark();
expect(IDENTIFIER, "Expecting type parameter name", TokenSet.orSet(TokenSet.create(COLON, COMMA), TYPE_REF_FIRST));
reference.done(REFERENCE_EXPRESSION);
if (expect(IDENTIFIER, "Expecting type parameter name", TokenSet.orSet(TokenSet.create(COLON, COMMA), TYPE_REF_FIRST))) {
reference.done(REFERENCE_EXPRESSION);
} else {
reference.drop();
}
expect(COLON, "Expecting ':' before the upper bound", TYPE_REF_FIRST);
@@ -1394,8 +1401,13 @@ public class JetParsing extends AbstractJetParsing {
PsiBuilder.Marker reference = mark();
while (true) {
expect(IDENTIFIER, "Expecting type name", TokenSet.orSet(JetExpressionParsing.EXPRESSION_FIRST, JetExpressionParsing.EXPRESSION_FOLLOW));
reference.done(REFERENCE_EXPRESSION);
if (expect(IDENTIFIER, "Expecting type name", TokenSet.orSet(JetExpressionParsing.EXPRESSION_FIRST, JetExpressionParsing.EXPRESSION_FOLLOW))) {
reference.done(REFERENCE_EXPRESSION);
}
else {
reference.drop();
break;
}
parseTypeArgumentList(-1);
if (!at(DOT)) {
@@ -81,27 +81,27 @@ public class JetSimpleNameExpression extends JetReferenceExpression {
@Nullable @IfNotParsed
public String getReferencedName() {
PsiElement referencedNameElement = getReferencedNameElement();
if (referencedNameElement == null) {
return null;
}
String text = referencedNameElement.getNode().getText();
String text = getReferencedNameElement().getNode().getText();
return text != null ? JetPsiUtil.unquoteIdentifierOrFieldReference(text) : null;
}
@Nullable @IfNotParsed
@NotNull
public PsiElement getReferencedNameElement() {
PsiElement element = findChildByType(REFERENCE_TOKENS);
if (element == null) {
element = findChildByType(JetExpressionParsing.ALL_OPERATIONS);
}
return element;
if (element != null) {
return element;
}
return this;
}
@Nullable @IfNotParsed
public IElementType getReferencedNameElementType() {
PsiElement element = getReferencedNameElement();
return element == null ? null : element.getNode().getElementType();
return getReferencedNameElement().getNode().getElementType();
}
@NotNull
@@ -194,27 +194,31 @@ public class ImportsResolver {
}
JetExpression selectorExpression = importedReference.getSelectorExpression();
assert selectorExpression instanceof JetSimpleNameExpression;
JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression;
JetSimpleNameExpression lastReference = getLastReference(receiverExpression);
if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference)) {
return Collections.emptyList();
}
Collection<? extends DeclarationDescriptor> result;
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
if (declarationDescriptor instanceof NamespaceDescriptor) {
result = lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), true);
if (!result.isEmpty()) return result;
if (selectorExpression instanceof JetSimpleNameExpression) {
JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression;
JetSimpleNameExpression lastReference = getLastReference(receiverExpression);
if (lastReference == null || !canImportMembersFrom(declarationDescriptors, lastReference)) {
return Collections.emptyList();
}
if (declarationDescriptor instanceof ClassDescriptor) {
result = lookupObjectMembers((ClassDescriptor) declarationDescriptor, selector);
if (!result.isEmpty()) return result;
}
if (declarationDescriptor instanceof VariableDescriptor) {
result = lookupVariableMembers((VariableDescriptor) declarationDescriptor, selector);
if (!result.isEmpty()) return result;
Collection<? extends DeclarationDescriptor> result;
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
if (declarationDescriptor instanceof NamespaceDescriptor) {
result = lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), true);
if (!result.isEmpty()) return result;
}
if (declarationDescriptor instanceof ClassDescriptor) {
result = lookupObjectMembers((ClassDescriptor) declarationDescriptor, selector);
if (!result.isEmpty()) return result;
}
if (declarationDescriptor instanceof VariableDescriptor) {
result = lookupVariableMembers((VariableDescriptor) declarationDescriptor, selector);
if (!result.isEmpty()) return result;
}
}
}
return Collections.emptyList();
}
@@ -31,7 +31,7 @@ import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.util.CommonSuppliers;
import org.jetbrains.jet.util.LinkedMultiMap;
import com.intellij.util.containers.LinkedMultiMap;
import java.util.*;
@@ -87,9 +87,11 @@ public class TypeCheckingProcedure {
}
for (int i = 0; i < type1Arguments.size(); i++) {
TypeParameterDescriptor typeParameter1 = constructor1.getParameters().get(i);
TypeProjection typeProjection1 = type1Arguments.get(i);
TypeParameterDescriptor typeParameter2 = constructor2.getParameters().get(i);
TypeProjection typeProjection2 = type2Arguments.get(i);
if (typeProjection1.getProjectionKind() != typeProjection2.getProjectionKind()) {
if (getEffectiveProjectionKind(typeParameter1, typeProjection1) != getEffectiveProjectionKind(typeParameter2, typeProjection2)) {
return false;
}
@@ -100,6 +102,58 @@ public class TypeCheckingProcedure {
return true;
}
private enum EnrichedProjectionKind {
IN, OUT, INV, STAR;
@NotNull
public static EnrichedProjectionKind fromVariance(@NotNull Variance variance) {
switch (variance) {
case INVARIANT:
return INV;
case IN_VARIANCE:
return IN;
case OUT_VARIANCE:
return OUT;
}
throw new IllegalStateException("Unknown variance");
}
}
// If class C<out T> then C<T> and C<out T> mean the same
// out * out = out
// out * in = *
// out * inv = out
//
// in * out = *
// in * in = in
// in * inv = in
//
// inv * out = out
// inv * in = out
// inv * inv = inv
private EnrichedProjectionKind getEffectiveProjectionKind(@NotNull TypeParameterDescriptor typeParameter, @NotNull TypeProjection typeArgument) {
Variance a = typeParameter.getVariance();
Variance b = typeArgument.getProjectionKind();
// If they are not both invariant, let's make b not invariant for sure
if (b == INVARIANT) {
Variance t = a;
a = b;
b = t;
}
// Opposites yield STAR
if (a == IN_VARIANCE && b == OUT_VARIANCE) {
return EnrichedProjectionKind.STAR;
}
if (a == OUT_VARIANCE && b == IN_VARIANCE) {
return EnrichedProjectionKind.STAR;
}
// If they are not opposite, return b, because b is either equal to a or b is in/out and a is inv
return EnrichedProjectionKind.fromVariance(b);
}
public boolean isSubtypeOf(@NotNull JetType subtype, @NotNull JetType supertype) {
if (ErrorUtils.isErrorType(subtype) || ErrorUtils.isErrorType(supertype)) {
return true;
@@ -127,7 +181,7 @@ public class TypeCheckingProcedure {
List<TypeProjection> subArguments = subtype.getArguments();
List<TypeProjection> superArguments = supertype.getArguments();
List<TypeParameterDescriptor> parameters = constructor.getParameters();
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
for (int i = 0; i < parameters.size(); i++) {
TypeParameterDescriptor parameter = parameters.get(i);
@@ -1,39 +0,0 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.util;
import com.intellij.util.containers.MultiMap;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author Evgeny Gerashchenko
* TODO reuse LinkedMultiMap from IDEA platform when it will be available there
*/
public class LinkedMultiMap<K, V> extends MultiMap<K, V> {
@Override
protected Map<K, Collection<V>> createMap() {
return new LinkedHashMap<K, Collection<V>>();
}
@Override
protected Map<K, Collection<V>> createMap(int i, float v) {
return new LinkedHashMap<K, Collection<V>>(i, v);
}
}
@@ -0,0 +1,13 @@
trait Creator<T> {
fun create() : T
}
class Actor(val code: String = "OK")
trait Factory : Creator<Actor>
class MyFactory() : Factory {
override fun create(): Actor = Actor()
}
fun box() : String = MyFactory().create().code
@@ -7,7 +7,7 @@ fun test(s: String?) {
val <!UNUSED_VARIABLE!>d<!>: Int = s?.length ?: <!TYPE_MISMATCH!>"empty"<!>
val e: String = <!TYPE_MISMATCH!>s?.length<!> ?: "empty"
val <!UNUSED_VARIABLE!>f<!>: Int = s?.length ?: b ?: 1
val <!UNUSED_VARIABLE!>g<!>: Int? = e? startsWith("s")?.length
val <!UNUSED_VARIABLE!>g<!>: Boolean? = e.startsWith("s")//?.length
}
fun String.startsWith(<!UNUSED_PARAMETER!>s<!>: String): Boolean = true
@@ -0,0 +1,8 @@
// +JDK
import java.util.ArrayList
class MyListOfPairs<T> : ArrayList<#(T, T)>() { }
fun test() {
MyListOfPairs<Int> : ArrayList<#(Int, Int)>
}
+15 -21
View File
@@ -92,9 +92,8 @@ JetFile: Imports_ERR.jet
PsiElement(IDENTIFIER)('foo')
PsiElement(DOT)('.')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiErrorElement:Expecting type name
PsiElement(as)('as')
PsiErrorElement:Expecting type name
PsiElement(as)('as')
PsiWhiteSpace(' ')
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
@@ -122,9 +121,8 @@ JetFile: Imports_ERR.jet
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiErrorElement:Expecting type name
PsiElement(MUL)('*')
PsiErrorElement:Expecting type name
PsiElement(MUL)('*')
PsiWhiteSpace(' ')
PsiErrorElement:Expecting namespace or top level declaration
PsiElement(as)('as')
@@ -156,9 +154,8 @@ JetFile: Imports_ERR.jet
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiErrorElement:Expecting type name
PsiElement(MUL)('*')
PsiErrorElement:Expecting type name
PsiElement(MUL)('*')
PsiWhiteSpace(' ')
PsiErrorElement:Expecting namespace or top level declaration
PsiElement(as)('as')
@@ -182,10 +179,9 @@ JetFile: Imports_ERR.jet
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(DOT)('.')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiErrorElement:Qualified name must be a '.'-separated identifier list
<empty list>
PsiErrorElement:Qualified name must be a '.'-separated identifier list
<empty list>
PsiWhiteSpace(' ')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n')
IMPORT_DIRECTIVE
@@ -199,10 +195,9 @@ JetFile: Imports_ERR.jet
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiElement(DOT)('.')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiErrorElement:Qualified name must be a '.'-separated identifier list
<empty list>
PsiErrorElement:Qualified name must be a '.'-separated identifier list
<empty list>
PsiWhiteSpace(' ')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n')
IMPORT_DIRECTIVE
@@ -212,10 +207,9 @@ JetFile: Imports_ERR.jet
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiElement(DOT)('.')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiErrorElement:Qualified name must be a '.'-separated identifier list
<empty list>
PsiErrorElement:Qualified name must be a '.'-separated identifier list
<empty list>
PsiWhiteSpace(' ')
PsiElement(as)('as')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('bar')
@@ -1,3 +0,0 @@
fun foo() {
a?f.foo
}
@@ -1,26 +0,0 @@
JetFile: PredicateExpression.jet
NAMESPACE_HEADER
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
PREDICATE_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(QUEST)('?')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('f')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -303,4 +303,8 @@ public class ClassGenTest extends CodegenTestCase {
blackBoxFile("regressions/kt633.kt");
}
public void testKt1345() throws Exception {
blackBoxFile("regressions/kt1345.kt");
}
}
@@ -88,19 +88,19 @@ public class StdlibTest extends CodegenTestCase {
}
//from NamespaceGenTest
public void testPredicateOperator() throws Exception {
loadText("fun foo(s: String) = s?startsWith(\"J\")");
final Method main = generateFunction();
try {
assertEquals("JetBrains", main.invoke(null, "JetBrains"));
assertNull(main.invoke(null, "IntelliJ"));
} catch (Throwable t) {
// System.out.println(generateToText());
t.printStackTrace();
throw t instanceof Exception ? (Exception)t : new RuntimeException(t);
}
}
// public void testPredicateOperator() throws Exception {
// loadText("fun foo(s: String) = s?startsWith(\"J\")");
// final Method main = generateFunction();
// try {
// assertEquals("JetBrains", main.invoke(null, "JetBrains"));
// assertNull(main.invoke(null, "IntelliJ"));
// } catch (Throwable t) {
//// System.out.println(generateToText());
// t.printStackTrace();
// throw t instanceof Exception ? (Exception)t : new RuntimeException(t);
// }
// }
//
public void testForInString() throws Exception {
loadText("fun foo() : Int { var sum = 0\n" +
" for(c in \"239\")\n" +
@@ -460,9 +460,9 @@ public class JetTypeCheckerTest extends JetLiteFixture {
assertType("true && false", "Boolean");
assertType("true || false", "Boolean");
assertType("null ?: false", "Boolean");
assertType("WithPredicate()?isValid()", "WithPredicate?");
assertType("WithPredicate()?isValid(1)", "WithPredicate?");
assertType("WithPredicate()?p", "WithPredicate?");
// assertType("WithPredicate()?isValid()", "WithPredicate?");
// assertType("WithPredicate()?isValid(1)", "WithPredicate?");
// assertType("WithPredicate()?p", "WithPredicate?");
}
public void testSupertypes() throws Exception {
@@ -471,6 +471,21 @@ public class JetTypeCheckerTest extends JetLiteFixture {
assertSupertypes("Derived1_inT<Int>", "Derived_T<Int>", "Base_T<Int>", "Any", "Base_inT<Int>");
}
public void testEffectiveProjectionKinds() throws Exception {
assertSubtype("Tuple1<Int>", "Tuple1<Int>");
assertSubtype("Tuple1<out Int>", "Tuple1<out Int>");
assertSubtype("Tuple1<out Int>", "Tuple1<Int>");
assertSubtype("Tuple1<Int>", "Tuple1<out Int>");
assertSubtype("Tuple1<in Int>", "Tuple1<out Any?>");
assertSubtype("Tuple1<out Any?>", "Tuple1<in String>");
assertSubtype("Base_inT<Int>", "Base_inT<Int>");
assertSubtype("Base_inT<in Int>", "Base_inT<in Int>");
assertSubtype("Base_inT<in Int>", "Base_inT<Int>");
assertSubtype("Base_inT<Int>", "Base_inT<in Int>");
assertSubtype("Base_inT<out Int>", "Base_inT<out Any?>");
assertSubtype("Base_inT<out Any?>", "Base_inT<out Int>");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void assertSupertypes(String typeStr, String... supertypeStrs) {