Merge branch 'master' of ssh://git.labs.intellij.net/jet

This commit is contained in:
svtk
2011-11-04 18:58:59 +04:00
36 changed files with 710 additions and 207 deletions
+3 -1
View File
@@ -4,6 +4,8 @@
<root url="jar://$PROJECT_DIR$/lib/asm-util-3.3.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
<SOURCES>
<root url="file://$USER_HOME$/libs/asm-3.3.1/src" />
</SOURCES>
</library>
</component>
@@ -0,0 +1,57 @@
package org.jetbrains.jet.codegen;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.util.TraceClassVisitor;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @author max
*/
public interface ClassBuilderFactory {
ClassBuilder newClassBuilder();
String asText(ClassBuilder builder);
byte[] asBytes(ClassBuilder builder);
ClassBuilderFactory TEXT = new ClassBuilderFactory() {
@Override
public ClassBuilder newClassBuilder() {
return new ClassBuilder(new TraceClassVisitor(new PrintWriter(new StringWriter())));
}
@Override
public String asText(ClassBuilder builder) {
TraceClassVisitor visitor = (TraceClassVisitor) builder.getVisitor();
StringWriter writer = new StringWriter();
visitor.print(new PrintWriter(writer));
return writer.toString();
}
@Override
public byte[] asBytes(ClassBuilder builder) {
throw new UnsupportedOperationException("TEXT generator asked for bytes");
}
};
ClassBuilderFactory BINARIES = new ClassBuilderFactory() {
@Override
public ClassBuilder newClassBuilder() {
return new ClassBuilder(new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
}
@Override
public String asText(ClassBuilder builder) {
throw new UnsupportedOperationException("BINARIES generator asked for text");
}
@Override
public byte[] asBytes(ClassBuilder builder) {
ClassWriter visitor = (ClassWriter) builder.getVisitor();
return visitor.toByteArray();
}
};
}
@@ -1,42 +1,26 @@
package org.jetbrains.jet.codegen;
import com.intellij.openapi.project.Project;
import org.jetbrains.jet.lang.psi.JetNamespace;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.util.TraceClassVisitor;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.*;
/**
* @author max
*/
public class ClassFileFactory {
private final Project project;
private final boolean isText;
private final ClassBuilderFactory builderFactory;
private final Map<String, NamespaceCodegen> ns2codegen = new HashMap<String, NamespaceCodegen>();
private final Map<String, ClassBuilder> generators = new LinkedHashMap<String, ClassBuilder>();
private boolean isDone = false;
public final GenerationState state;
public ClassFileFactory(Project project, boolean text, GenerationState state) {
this.project = project;
isText = text;
public ClassFileFactory(ClassBuilderFactory builderFactory, GenerationState state) {
this.builderFactory = builderFactory;
this.state = state;
}
ClassBuilder newVisitor(String filePath) {
ClassVisitor visitor;
if (isText) {
visitor = new TraceClassVisitor(new PrintWriter(new StringWriter()));
}
else {
visitor = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
}
final ClassBuilder answer = new ClassBuilder(visitor);
final ClassBuilder answer = builderFactory.newClassBuilder();
generators.put(filePath, answer);
return answer;
}
@@ -68,25 +52,13 @@ public class ClassFileFactory {
}
public String asText(String file) {
assert isText : "Need to create with text=true";
done();
TraceClassVisitor visitor = (TraceClassVisitor) generators.get(file).getVisitor();
StringWriter writer = new StringWriter();
visitor.print(new PrintWriter(writer));
return writer.toString();
return builderFactory.asText(generators.get(file));
}
public byte[] asBytes(String file) {
assert !isText : "This is debug stuff, only produces texts.";
done();
ClassWriter visitor = (ClassWriter) generators.get(file).getVisitor();
return visitor.toByteArray();
return builderFactory.asBytes(generators.get(file));
}
public List<String> files() {
@@ -69,7 +69,7 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
signatureWriter.visitEnd();
cv.defineClass(V1_6,
ACC_PUBLIC,
ACC_PUBLIC/*|ACC_SUPER*/,
name,
null,
funClass,
@@ -1,14 +1,9 @@
package org.jetbrains.jet.codegen;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetClass;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeProjection;
import org.objectweb.asm.Type;
/**
@@ -67,39 +62,4 @@ public class CodegenUtil {
return hasOuterTypeInfo(outerClassDescriptor);
}
public static boolean hasTypeInfoField(JetType type) {
if(type.getConstructor().getParameters().size() > 0)
return true;
for (JetType jetType : type.getConstructor().getSupertypes()) {
if(hasTypeInfoField(jetType))
return true;
}
ClassDescriptor outerClassDescriptor = getOuterClassDescriptor(type.getConstructor().getDeclarationDescriptor());
if(outerClassDescriptor == null)
return false;
return hasTypeInfoField(outerClassDescriptor.getDefaultType());
}
public static boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
if(!exceptOwn) {
if(!isInterface(type))
if(hasTypeInfoField(type))
return true;
}
for (JetType jetType : type.getConstructor().getSupertypes()) {
if(hasDerivedTypeInfoField(jetType, false))
return true;
}
return false;
}
public static Type arrayElementType(Type type) {
return Type.getType(type.getDescriptor().substring(1));
}
}
@@ -128,6 +128,23 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
throw new UnsupportedOperationException("Codegen for " + expression + " is not yet implemented");
}
@Override
public StackValue visitNamedFunction(JetNamedFunction function, StackValue data) {
throw new UnsupportedOperationException("Codegen for named functions is not yet implemented");
}
@Override
public StackValue visitSuperExpression(JetSuperExpression expression, StackValue data) {
// final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, expression.getInstanceReference());
// if (descriptor instanceof ClassDescriptor) {
// return generateThisOrOuter((ClassDescriptor) descriptor);
// }
// else {
// return thisExpression();
// }
return StackValue.none();
}
@Override
public StackValue visitParenthesizedExpression(JetParenthesizedExpression expression, StackValue receiver) {
return genQualified(receiver, expression.getExpression());
@@ -285,7 +302,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
// if(hND != null)
// invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
// else
intermediateValueForProperty((PropertyDescriptor) hasNextDescriptor, false, false).put(Type.BOOLEAN_TYPE, v);
intermediateValueForProperty((PropertyDescriptor) hasNextDescriptor, false, false, false).put(Type.BOOLEAN_TYPE, v);
}
v.ifeq(end);
@@ -793,16 +810,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
else {
boolean isStatic = container instanceof NamespaceDescriptorImpl;
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER;
final boolean directToField = expression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER && contextKind() != OwnerKind.TRAIT_IMPL ;
JetExpression r = getReceiverForSelector(expression);
final boolean forceInterface = r != null && !(r instanceof JetThisExpression);
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, forceInterface);
final boolean isSuper = r instanceof JetSuperExpression;
final StackValue iValue = intermediateValueForProperty(propertyDescriptor, directToField, forceInterface, isSuper);
if (!isStatic) {
if (receiver == StackValue.none()) {
receiver = generateThisOrOuter((ClassDescriptor) propertyDescriptor.getContainingDeclaration());
}
JetType receiverType = bindingContext.get(BindingContext.EXPRESSION_TYPE, r);
receiver.put(receiverType != null ? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
receiver.put(receiverType != null && !isSuper? typeMapper.mapType(receiverType) : JetTypeMapper.TYPE_OBJECT, v);
if(receiverType != null) {
ClassDescriptor propReceiverDescriptor = (ClassDescriptor) propertyDescriptor.getContainingDeclaration();
if(!CodegenUtil.isInterface(propReceiverDescriptor) && CodegenUtil.isInterface(receiverType.getConstructor().getDeclarationDescriptor())) {
@@ -895,11 +913,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
StackValue.onStack(typeMapper.mapType(functionDescriptor.getReturnType())).coerce(type, v);
}
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, boolean forceInterface) {
public StackValue intermediateValueForProperty(PropertyDescriptor propertyDescriptor, final boolean forceField, boolean forceInterface, boolean isSuper) {
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
propertyDescriptor = propertyDescriptor.getOriginal();
boolean isInsideClass = !forceInterface && containingDeclaration == context.getContextClass();
boolean isInsideClass = !forceInterface && containingDeclaration == context.getContextClass() && contextKind() != OwnerKind.TRAIT_IMPL;
Method getter;
Method setter;
if (forceField) {
@@ -909,10 +927,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
else {
//noinspection ConstantConditions
getter = isInsideClass && (propertyDescriptor.getGetter() == null || propertyDescriptor.getGetter().isDefault())
? null : typeMapper.mapGetterSignature(propertyDescriptor);
? null : typeMapper.mapGetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
//noinspection ConstantConditions
setter = isInsideClass && (propertyDescriptor.getSetter() == null || propertyDescriptor.getSetter().isDefault())
? null : typeMapper.mapSetterSignature(propertyDescriptor);
? null : typeMapper.mapSetterSignature(propertyDescriptor, OwnerKind.IMPLEMENTATION);
}
String owner;
@@ -931,7 +949,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
}
return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(propertyDescriptor.getOutType()), isStatic, isInterface, getter, setter);
return StackValue.property(propertyDescriptor.getName(), owner, typeMapper.mapType(propertyDescriptor.getOutType()), isStatic, isInterface, isSuper, getter, setter);
}
@Override
@@ -1009,10 +1027,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private DeclarationDescriptor resolveCalleeDescriptor(JetCallExpression call) {
JetExpression callee = call.getCalleeExpression();
if (!(callee instanceof JetSimpleNameExpression)) {
if (!(callee instanceof JetReferenceExpression)) {
throw new UnsupportedOperationException("Don't know how to generate a call to " + callee);
}
DeclarationDescriptor funDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) callee);
DeclarationDescriptor funDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression) callee);
if (funDescriptor == null) {
throw new CompilationException("Cannot resolve: " + callee.getText());
}
@@ -1883,7 +1901,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Type type = JetTypeMapper.psiClassType(javaClass);
v.anew(type);
v.dup();
final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructor);
final CallableMethod callableMethod = JetTypeMapper.mapToCallableMethod(constructor);
invokeMethodWithArguments(callableMethod, expression, StackValue.none());
return type;
}
@@ -2071,6 +2089,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return generateThisOrOuter((ClassDescriptor) descriptor);
}
else {
// estension function or ???
return thisExpression();
}
}
@@ -2260,7 +2279,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private void generateInstanceOf(StackValue expressionToGen, JetType jetType, boolean leaveExpressionOnStack) {
DeclarationDescriptor descriptor = jetType.getConstructor().getDeclarationDescriptor();
if (jetType.getArguments().size() > 0 || !(descriptor instanceof ClassDescriptor)) {
boolean javaClass = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor) instanceof PsiClass;
if (!javaClass && (jetType.getArguments().size() > 0 || !(descriptor instanceof ClassDescriptor))) {
generateTypeInfo(jetType);
expressionToGen.put(OBJECT_TYPE, v);
if (leaveExpressionOnStack) {
@@ -2306,7 +2326,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return;
}
if(!CodegenUtil.hasTypeInfoField(jetType)) {
if(!typeMapper.hasTypeInfoField(jetType) && !(bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetType.getConstructor().getDeclarationDescriptor()) instanceof PsiClass)) {
// TODO: we need some better checks here
v.getstatic(typeMapper.mapType(jetType, OwnerKind.IMPLEMENTATION).getInternalName(), "$staticTypeInfo", "Ljet/typeinfo/TypeInfo;");
return;
@@ -2368,7 +2388,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
ownerType = JetTypeMapper.boxType(ownerType);
if (containingDeclaration == context.getContextClass()) {
if(!CodegenUtil.isInterface(descriptor)) {
if (CodegenUtil.hasTypeInfoField(defaultType)) {
if (typeMapper.hasTypeInfoField(defaultType)) {
v.load(0, JetTypeMapper.TYPE_OBJECT);
v.getfield(ownerType.getInternalName(), "$typeInfo", "Ljet/typeinfo/TypeInfo;");
}
@@ -2481,7 +2501,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call);
if (descriptor instanceof PropertyDescriptor) {
v.load(subjectLocal, subjectType);
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, false);
conditionValue = intermediateValueForProperty((PropertyDescriptor) descriptor, false, false, false);
}
else {
throw new UnsupportedOperationException("unknown simple name resolve result: " + descriptor);
@@ -28,10 +28,10 @@ public class GenerationState {
private final JetStandardLibrary standardLibrary;
private final IntrinsicMethods intrinsics;
public GenerationState(Project project, boolean text) {
public GenerationState(Project project, ClassBuilderFactory builderFactory) {
this.project = project;
this.standardLibrary = JetStandardLibrary.getJetStandardLibrary(project);
this.factory = new ClassFileFactory(project, text, this);
this.factory = new ClassFileFactory(builderFactory, this);
this.intrinsics = new IntrinsicMethods(project, standardLibrary);
}
@@ -95,7 +95,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | (isAbstract ? Opcodes.ACC_ABSTRACT : 0) | (isInterface
? Opcodes.ACC_INTERFACE
: 0),
: 0/*Opcodes.ACC_SUPER*/),
jvmName(),
null,
superClass,
@@ -339,7 +339,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.putfield(classname, fieldName, interfaceDesc);
}
if (CodegenUtil.hasTypeInfoField(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
if (state.getTypeMapper().hasTypeInfoField(descriptor.getDefaultType()) && kind == OwnerKind.IMPLEMENTATION) {
generateTypeInfoInitializer(frameMap.getFirstTypeParameter(), frameMap.getTypeParameterCount(), iv);
}
@@ -652,7 +652,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
if(propertyDescriptor.getOutType().isNullable())
type = JetTypeMapper.boxType(type);
codegen.gen(initializer, type);
codegen.intermediateValueForProperty(propertyDescriptor, false, false).store(iv);
codegen.intermediateValueForProperty(propertyDescriptor, false, false, false).store(iv);
}
}
@@ -706,8 +706,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
return;
JetType defaultType = descriptor.getDefaultType();
if(CodegenUtil.hasTypeInfoField(defaultType)) {
if(!CodegenUtil.hasDerivedTypeInfoField(defaultType, true)) {
if(state.getTypeMapper().hasTypeInfoField(defaultType)) {
if(!state.getTypeMapper().hasDerivedTypeInfoField(defaultType, true)) {
v.newField(myClass, Opcodes.ACC_PRIVATE, "$typeInfo", "Ljet/typeinfo/TypeInfo;", null, null);
MethodVisitor mv = v.newMethod(myClass, Opcodes.ACC_PUBLIC, "getTypeInfo", "()Ljet/typeinfo/TypeInfo;", null, null);
@@ -186,6 +186,39 @@ public class JetTypeMapper {
return type;
}
public boolean hasTypeInfoField(JetType type) {
if(type.getConstructor().getParameters().size() > 0) {
if(!(bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, type.getConstructor().getDeclarationDescriptor()) instanceof PsiClass))
return true;
}
for (JetType jetType : type.getConstructor().getSupertypes()) {
if(hasTypeInfoField(jetType))
return true;
}
ClassDescriptor outerClassDescriptor = CodegenUtil.getOuterClassDescriptor(type.getConstructor().getDeclarationDescriptor());
if(outerClassDescriptor == null)
return false;
return hasTypeInfoField(outerClassDescriptor.getDefaultType());
}
public boolean hasDerivedTypeInfoField(JetType type, boolean exceptOwn) {
if(!exceptOwn) {
if(!CodegenUtil.isInterface(type))
if(hasTypeInfoField(type))
return true;
}
for (JetType jetType : type.getConstructor().getSupertypes()) {
if(hasDerivedTypeInfoField(jetType, false))
return true;
}
return false;
}
public String jvmName(ClassDescriptor jetClass, OwnerKind kind) {
PsiElement declaration = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, jetClass);
if (declaration instanceof PsiClass) {
@@ -627,18 +660,29 @@ public class JetTypeMapper {
answer.append(p.getName()); // TODO: BOUND!
}
public Method mapGetterSignature(PropertyDescriptor descriptor) {
public Method mapGetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
Type returnType = mapType(descriptor.getOutType());
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
if(kind != OwnerKind.TRAIT_IMPL)
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[0]);
else {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
return new Method(PropertyCodegen.getterName(descriptor.getName()), returnType, new Type[] { mapType(containingDeclaration.getDefaultType()) });
}
}
public Method mapSetterSignature(PropertyDescriptor descriptor) {
public Method mapSetterSignature(PropertyDescriptor descriptor, OwnerKind kind) {
final JetType inType = descriptor.getInType();
if (inType == null) {
return null;
}
Type paramType = mapType(inType);
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { paramType });
if(kind != OwnerKind.TRAIT_IMPL) {
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { paramType });
}
else {
ClassDescriptor containingDeclaration = (ClassDescriptor) descriptor.getContainingDeclaration();
return new Method(PropertyCodegen.setterName(descriptor.getName()), Type.VOID_TYPE, new Type[] { mapType(containingDeclaration.getDefaultType()), paramType });
}
}
private Method mapConstructorSignature(ConstructorDescriptor descriptor, List<Type> valueParameterTypes) {
@@ -654,9 +698,12 @@ public class JetTypeMapper {
valueParameterTypes.add(type);
}
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
for (int n = typeParameters.size(); n > 0; n--) {
parameterTypes.add(TYPE_TYPEINFO);
PsiElement psiElement = bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, classDescriptor);
if(!(psiElement instanceof PsiClass)) {
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
for (int n = typeParameters.size(); n > 0; n--) {
parameterTypes.add(TYPE_TYPEINFO);
}
}
return new Method("<init>", Type.VOID_TYPE, parameterTypes.toArray(new Type[parameterTypes.size()]));
@@ -667,7 +714,7 @@ public class JetTypeMapper {
final Method method = mapConstructorSignature(descriptor, valueParameterTypes);
String owner = jvmName(descriptor.getContainingDeclaration(), kind);
final CallableMethod result = new CallableMethod(owner, method, Opcodes.INVOKESPECIAL, valueParameterTypes);
result.setAcceptsTypeArguments(true);
result.setAcceptsTypeArguments(!(bindingContext.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor.getContainingDeclaration()) instanceof PsiClass));
return result;
}
@@ -32,7 +32,7 @@ public class NamespaceCodegen {
this.state = state;
v.defineClass(V1_6,
ACC_PUBLIC,
ACC_PUBLIC/*|ACC_SUPER*/,
getJVMClassName(fqName),
null,
//"jet/lang/Namespace",
@@ -93,7 +93,7 @@ public class NamespaceCodegen {
if (initializer != null && !(initializer instanceof JetConstantExpression)) {
final PropertyDescriptor descriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, declaration);
codegen.genToJVMStack(initializer);
codegen.intermediateValueForProperty(descriptor, true, false).store(new InstructionAdapter(mv));
codegen.intermediateValueForProperty(descriptor, true, false, false).store(new InstructionAdapter(mv));
}
}
}
@@ -37,8 +37,9 @@ public class PropertyCodegen {
throw new UnsupportedOperationException("expect a property to have a property descriptor");
}
final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION) {
generateBackingField(p, propertyDescriptor);
if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind ==OwnerKind.TRAIT_IMPL ) {
if(kind != OwnerKind.TRAIT_IMPL)
generateBackingField(p, propertyDescriptor);
generateGetter(p, propertyDescriptor);
generateSetter(p, propertyDescriptor);
}
@@ -81,7 +82,7 @@ public class PropertyCodegen {
final JetPropertyAccessor getter = p.getGetter();
if (getter != null) {
if (getter.getBodyExpression() != null) {
functionCodegen.generateMethod(getter, state.getTypeMapper().mapGetterSignature(propertyDescriptor), propertyDescriptor.getGetter());
functionCodegen.generateMethod(getter, state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind), propertyDescriptor.getGetter());
}
else if (!getter.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
generateDefaultGetter(p, getter);
@@ -102,7 +103,7 @@ public class PropertyCodegen {
if (setter.getBodyExpression() != null) {
final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
assert setterDescriptor != null;
functionCodegen.generateMethod(setter, state.getTypeMapper().mapSetterSignature(propertyDescriptor), setterDescriptor);
functionCodegen.generateMethod(setter, state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind), setterDescriptor);
}
else if (!p.hasModifier(JetTokens.PRIVATE_KEYWORD)) {
generateDefaultSetter(p, setter);
@@ -120,6 +121,10 @@ public class PropertyCodegen {
}
public void generateDefaultGetter(PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) {
if (kind == OwnerKind.TRAIT_IMPL) {
return;
}
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
@@ -129,7 +134,7 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor).getDescriptor();
final String signature = state.getTypeMapper().mapGetterSignature(propertyDescriptor, kind).getDescriptor();
String getterName = getterName(propertyDescriptor.getName());
MethodVisitor mv = v.newMethod(origin, flags, getterName, signature, null, null);
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
@@ -162,6 +167,10 @@ public class PropertyCodegen {
}
public void generateDefaultSetter(PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) {
if (kind == OwnerKind.TRAIT_IMPL) {
return;
}
if (kind == OwnerKind.NAMESPACE) {
flags |= Opcodes.ACC_STATIC;
}
@@ -171,7 +180,7 @@ public class PropertyCodegen {
if(isTrait && !(kind instanceof OwnerKind.DelegateKind))
flags |= Opcodes.ACC_ABSTRACT;
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor).getDescriptor();
final String signature = state.getTypeMapper().mapSetterSignature(propertyDescriptor, kind).getDescriptor();
MethodVisitor mv = v.newMethod(origin, flags, setterName(propertyDescriptor.getName()), signature, null, null);
if (!isTrait || kind instanceof OwnerKind.DelegateKind) {
mv.visitCode();
@@ -96,8 +96,8 @@ public abstract class StackValue {
return new InstanceField(type, owner, name);
}
public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, Method getter, Method setter) {
return new Property(name, owner, getter, setter, isStatic, isInterface, type);
public static StackValue property(String name, String owner, Type type, boolean isStatic, boolean isInterface, boolean isSuper, Method getter, Method setter) {
return new Property(name, owner, getter, setter, isStatic, isInterface, isSuper, type);
}
public static StackValue expression(Type type, JetExpression expression, ExpressionCodegen generator) {
@@ -623,8 +623,9 @@ public abstract class StackValue {
private final String owner;
private final boolean isStatic;
private final boolean isInterface;
private boolean isSuper;
public Property(String name, String owner, Method getter, Method setter, boolean aStatic, boolean isInterface, Type type) {
public Property(String name, String owner, Method getter, Method setter, boolean aStatic, boolean isInterface, boolean isSuper, Type type) {
super(type);
this.name = name;
this.owner = owner;
@@ -632,26 +633,37 @@ public abstract class StackValue {
this.setter = setter;
isStatic = aStatic;
this.isInterface = isInterface;
this.isSuper = isSuper;
}
@Override
public void put(Type type, InstructionAdapter v) {
if (getter == null) {
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
if(isSuper && isInterface) {
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", getter.getName(), getter.getDescriptor().replace("(","(L" + owner + ";"));
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
if (getter == null) {
v.visitFieldInsn(isStatic ? Opcodes.GETSTATIC : Opcodes.GETFIELD, owner, name, this.type.getDescriptor());
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, getter.getName(), getter.getDescriptor());
}
}
coerce(type, v);
}
@Override
public void store(InstructionAdapter v) {
if (setter == null) {
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
if(isSuper && isInterface) {
v.visitMethodInsn(Opcodes.INVOKESTATIC, owner + "$$TImpl", setter.getName(), setter.getDescriptor().replace("(","(L" + owner + ";"));
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
if (setter == null) {
v.visitFieldInsn(isStatic ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, owner, name, this.type.getDescriptor());
}
else {
v.visitMethodInsn(isStatic ? Opcodes.INVOKESTATIC : isSuper ? Opcodes.INVOKESPECIAL : isInterface ? Opcodes.INVOKEINTERFACE : Opcodes.INVOKEVIRTUAL, owner, setter.getName(), setter.getDescriptor());
}
}
}
@@ -46,7 +46,7 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
@Override
protected void generateDeclaration() {
v.defineClass(Opcodes.V1_6,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL,
Opcodes.ACC_PUBLIC | Opcodes.ACC_FINAL/*| Opcodes.ACC_SUPER*/,
jvmName(),
null,
"java/lang/Object",
@@ -4,10 +4,13 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import jet.modules.IModuleBuilder;
import jet.modules.IModuleSetBuilder;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GeneratedClassLoader;
@@ -40,7 +43,7 @@ public class CompileEnvironment {
myEnvironment = new JetCoreEnvironment(myRootDisposable);
}
public void setMyErrorStream(PrintStream errorStream) {
public void setErrorStream(PrintStream errorStream) {
myErrorStream = errorStream;
}
@@ -86,7 +89,35 @@ public class CompileEnvironment {
myEnvironment.addToClasspath(rtJarPath);
}
public static File findActiveRtJar() {
public static File findRtJar(boolean failOnError) {
String javaHome = System.getenv("JAVA_HOME");
File rtJar;
if (javaHome == null) {
rtJar = findActiveRtJar(failOnError);
if(rtJar == null && failOnError) {
throw new CompileEnvironmentException("JAVA_HOME environment variable needs to be defined");
}
}
else {
rtJar = findRtJar(javaHome);
}
if ((rtJar == null || !rtJar.exists()) && failOnError) {
throw new CompileEnvironmentException("No rt.jar found under JAVA_HOME=" + javaHome);
}
return rtJar;
}
private static File findRtJar(String javaHome) {
File rtJar = new File(javaHome, "jre/lib/rt.jar");
if (rtJar.exists()) {
return rtJar;
}
return null;
}
public static File findActiveRtJar(boolean failOnError) {
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
if (systemClassLoader instanceof URLClassLoader) {
URLClassLoader loader = (URLClassLoader) systemClassLoader;
@@ -100,6 +131,17 @@ public class CompileEnvironment {
}
}
}
if (failOnError) {
throw new CompileEnvironmentException("Could not find rt.jar in system class loader: " + StringUtil.join(loader.getURLs(), new Function<URL, String>() {
@Override
public String fun(URL url) {
return url.toString();
}
}, ", "));
}
}
else if (failOnError) {
throw new CompileEnvironmentException("System class loader is not an URLClassLoader: " + systemClassLoader);
}
return null;
}
@@ -113,7 +155,12 @@ public class CompileEnvironment {
final String directory = new File(moduleFile).getParent();
for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) {
ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory);
writeToJar(moduleFactory, new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(), null, true);
final String path = new File(directory, moduleBuilder.getModuleName() + ".jar").getPath();
try {
writeToJar(moduleFactory, new FileOutputStream(path), null, true);
} catch (FileNotFoundException e) {
throw new CompileEnvironmentException("Invalid jar path " + path, e);
}
}
}
@@ -191,7 +238,7 @@ public class CompileEnvironment {
return new File(PathManager.getResourceRoot(CompileEnvironment.class, "/org/jetbrains/jet/compiler/CompileEnvironment.class")).getParentFile().getParentFile().getParent();
}
public static void writeToJar(ClassFileFactory factory, String jar, String mainClass, boolean includeRuntime) {
public static void writeToJar(ClassFileFactory factory, final OutputStream fos, @Nullable String mainClass, boolean includeRuntime) {
try {
Manifest manifest = new Manifest();
final Attributes mainAttributes = manifest.getMainAttributes();
@@ -200,7 +247,6 @@ public class CompileEnvironment {
if (mainClass != null) {
mainAttributes.putValue("Main-Class", mainClass);
}
FileOutputStream fos = new FileOutputStream(jar);
JarOutputStream stream = new JarOutputStream(fos, manifest);
try {
for (String file : factory.files()) {
@@ -286,7 +332,11 @@ public class CompileEnvironment {
ClassFileFactory factory = session.generate();
if (jar != null) {
writeToJar(factory, jar, mainClass, true);
try {
writeToJar(factory, new FileOutputStream(jar), mainClass, true);
} catch (FileNotFoundException e) {
throw new CompileEnvironmentException("Invalid jar path " + jar, e);
}
}
else if (outputDir != null) {
writeToOutputDirectory(factory, outputDir);
@@ -5,6 +5,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import org.jetbrains.jet.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
@@ -93,7 +94,7 @@ public class CompileSession {
}
public ClassFileFactory generate() {
GenerationState generationState = new GenerationState(myEnvironment.getProject(), false);
GenerationState generationState = new GenerationState(myEnvironment.getProject(), ClassBuilderFactory.BINARIES);
generationState.compileCorrectNamespaces(myBindingContext, mySourceFileNamespaces);
return generationState.getFactory();
}
@@ -5,8 +5,6 @@ import com.sampullara.cli.Argument;
import org.jetbrains.jet.compiler.CompileEnvironment;
import org.jetbrains.jet.compiler.CompileEnvironmentException;
import java.io.File;
/**
* @author yole
* @author alex.tkachman
@@ -38,11 +36,8 @@ public class KotlinCompiler {
CompileEnvironment environment = new CompileEnvironment();
File rtJar = initJdk();
if (rtJar == null) return;
try {
environment.setJavaRuntime(rtJar);
environment.setJavaRuntime(CompileEnvironment.findRtJar(true));
if (!environment.initializeKotlinRuntime()) {
System.out.println("No runtime library found");
return;
@@ -60,33 +55,4 @@ public class KotlinCompiler {
}
}
private static File initJdk() {
String javaHome = System.getenv("JAVA_HOME");
File rtJar;
if (javaHome == null) {
rtJar = CompileEnvironment.findActiveRtJar();
if(rtJar == null) {
System.out.println("JAVA_HOME environment variable needs to be defined");
return null;
}
}
else {
rtJar = findRtJar(javaHome);
}
if (rtJar == null || !rtJar.exists()) {
System.out.print("No rt.jar found under JAVA_HOME=" + javaHome);
return null;
}
return rtJar;
}
private static File findRtJar(String javaHome) {
File rtJar = new File(javaHome, "jre/lib/rt.jar");
if (rtJar.exists()) {
return rtJar;
}
return null;
}
}
@@ -240,6 +240,8 @@ public interface Errors {
SimpleDiagnosticFactory SUPERTYPE_APPEARS_TWICE = SimpleDiagnosticFactory.create(ERROR, "A supertype appears twice");
SimpleDiagnosticFactory FINAL_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "This type is final, so it cannot be inherited from");
ParameterizedDiagnosticFactory1<String> ILLEGAL_SELECTOR = ParameterizedDiagnosticFactory1.create(ERROR, "Expression ''{0}'' cannot be a selector (occur after a dot)");
SimpleDiagnosticFactory REF_PARAMETER_WITH_VAL_OR_VAR = SimpleDiagnosticFactory.create(ERROR, "'val' and 'var' are not allowed on ref-parameters");
SimpleDiagnosticFactory VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION = SimpleDiagnosticFactory.create(ERROR, "A type annotation is required on a value parameter");
SimpleDiagnosticFactory BREAK_OR_CONTINUE_OUTSIDE_A_LOOP = SimpleDiagnosticFactory.create(ERROR, "'break' and 'continue' are only allowed inside a loop");
@@ -1,9 +1,12 @@
package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collections;
import java.util.List;
@@ -46,7 +49,32 @@ public class JetCallExpression extends JetExpression implements JetCallElement {
@Override
@NotNull
public List<JetExpression> getFunctionLiteralArguments() {
return findChildrenByType(JetNodeTypes.FUNCTION_LITERAL_EXPRESSION);
JetExpression calleeExpression = getCalleeExpression();
ASTNode node;
if (calleeExpression instanceof JetFunctionLiteralExpression) {
node = calleeExpression.getNode().getTreeNext();
}
else {
node = getNode().getFirstChildNode();
}
List<JetExpression> result = new SmartList<JetExpression>();
while (node != null) {
PsiElement psi = node.getPsi();
if (psi instanceof JetFunctionLiteralExpression) {
result.add((JetFunctionLiteralExpression) psi);
}
else if (psi instanceof JetPrefixExpression) {
JetPrefixExpression prefixExpression = (JetPrefixExpression) psi;
if (JetTokens.LABELS.contains(prefixExpression.getOperationSign().getReferencedNameElementType())) {
JetExpression labeledExpression = prefixExpression.getBaseExpression();
if (labeledExpression instanceof JetFunctionLiteralExpression) {
result.add(labeledExpression);
}
}
}
node = node.getTreeNext();
}
return result;
}
@Override
@@ -177,7 +177,7 @@ public class CallResolver {
else if (calleeExpression != null) {
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
ExpressionTypingServices typingServices = new ExpressionTypingServices(semanticServices, trace);
JetType calleeType = typingServices.safeGetType(scope, calleeExpression, NO_EXPECTED_TYPE);// We are actually expecting a function, but there seems to be no easy way of expressing this
JetType calleeType = typingServices.safeGetType(scope, calleeExpression, NO_EXPECTED_TYPE); // We are actually expecting a function, but there seems to be no easy way of expressing this
if (!JetStandardClasses.isFunctionType(calleeType)) {
checkTypesWithNoCallee(trace, scope, call);
@@ -187,13 +187,17 @@ public class CallResolver {
return null;
}
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), "for expression " + calleeExpression.getText());
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType);
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
resolvedCall.setReceiverArgument(call.getExplicitReceiver());
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(
Collections.singleton(resolvedCall), call, dataFlowInfo));
functionReference = new JetReferenceExpression(calleeExpression.getNode()) {
};
// strictly speaking, this is a hack:
// we need to pass a reference, but there's no reference in the PSI,
// so we wrap what we have into a fake reference and pass it on (unwrap on the other end)
functionReference = new JetFakeReference(calleeExpression);
}
else {
checkTypesWithNoCallee(trace, scope, call);
@@ -238,9 +242,17 @@ public class CallResolver {
// trace.record(REFERENCE_TARGET, reference, variableAsFunctionDescriptor.getVariableDescriptor());
// }
// else {
trace.record(REFERENCE_TARGET, reference, descriptor);
// }
trace.record(RESOLVED_CALL, reference, resolvedCall);
if (reference instanceof JetFakeReference) {
// This means that the callable being invoked was represented by an expression
// rather than a reference expression
JetFakeReference fakeReference = (JetFakeReference) reference;
trace.record(RESOLVED_CALL, fakeReference.getActualElement(), resolvedCall);
}
else {
trace.record(RESOLVED_CALL, reference, resolvedCall);
trace.record(REFERENCE_TARGET, reference, descriptor);
}
}
@Override
@@ -471,23 +483,18 @@ public class CallResolver {
else {
// Explicit type arguments passed
for (JetTypeProjection typeArgument : jetTypeArguments) {
if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
// temporaryTrace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
temporaryTrace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeArgument));
List<JetType> typeArguments = new ArrayList<JetType>();
for (JetTypeProjection projection : jetTypeArguments) {
if (projection.getProjectionKind() != JetProjectionKind.NONE) {
temporaryTrace.report(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(projection));
}
JetTypeReference typeReference = projection.getTypeReference();
if (typeReference != null) {
typeArguments.add(new TypeResolver(semanticServices, temporaryTrace, true).resolveType(scope, typeReference));
}
}
int expectedTypeArgumentCount = candidate.getTypeParameters().size();
if (expectedTypeArgumentCount == jetTypeArguments.size()) {
List<JetType> typeArguments = new ArrayList<JetType>();
for (JetTypeProjection projection : jetTypeArguments) {
// TODO : check that there's no projection
JetTypeReference typeReference = projection.getTypeReference();
if (typeReference != null) {
typeArguments.add(new TypeResolver(semanticServices, temporaryTrace, true).resolveType(scope, typeReference));
}
}
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, temporaryTrace);
@@ -0,0 +1,24 @@
package org.jetbrains.jet.lang.resolve.calls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
/**
*
* This class is used to wrap an expression that occurs in a reference position, such as a function literal, into a reference expression
*
* @author abreslav
*/
public class JetFakeReference extends JetReferenceExpression {
private final JetElement actualElement;
public JetFakeReference(@NotNull JetElement actualElement) {
super(actualElement.getNode());
this.actualElement = actualElement;
}
public JetElement getActualElement() {
return actualElement;
}
}
@@ -525,8 +525,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
}
else {
// TODO : not a simple name -> resolve in scope, expect property type or a function type
context.trace.report(UNSUPPORTED.on(selectorExpression, "getSelectorReturnType"));
context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression, selectorExpression.getText()));
}
return null;
}
@@ -47,4 +47,36 @@ fun main(args : Array<String>) {
<!CALLEE_NOT_A_FUNCTION!>1<!>()
<!CALLEE_NOT_A_FUNCTION!>1<!>{}
<!CALLEE_NOT_A_FUNCTION!>1<!>(){}
}
fun f() : fun Int.() : Unit = {}
fun main1(args : Array<String>) {
1.{Int.() => 1}();
{1}()
{(x : Int) => x}(1)
1.{Int.(x : Int) => x}(1)
@l{1}()
1.({Int.() => 1})()
1.(f())()
1.if(true){f()}else{f()}()
1.if(true){Int.() => 1}else{f()}()
1.if(true){Int.() => 1}else{Int.() => 1}()
1.<!CALLEE_NOT_A_FUNCTION!>"sdf"<!>()
1.<!ILLEGAL_SELECTOR!>"sdf"<!>
1.<!ILLEGAL_SELECTOR!>{}<!>
1.<!ILLEGAL_SELECTOR!>if (true) {}<!>
}
fun test() {
{(x : Int) => 1}<!NO_VALUE_FOR_PARAMETER!>()<!>
<!MISSING_RECEIVER!>{Int.() => 1}<!>()
<!TYPE_MISMATCH!>"sd"<!>.{Int.() => 1}()
val i : Int? = null
i<!UNSAFE_CALL!>.<!>{Int.() => 1}()
{}<!WRONG_NUMBER_OF_TYPE_ARGUMENTS!><Int><!>()
1<!UNNECESSARY_SAFE_CALL!>?.<!>{Int.() => 1}()
1.<!NO_RECEIVER_ADMITTED!>{}<!>()
}
@@ -0,0 +1,4 @@
fun test() {
fun <T> foo(){}
foo<<!PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT!>in Int<!>>()
}
@@ -0,0 +1,7 @@
// KT-439 Support labeled function lliterals in call arguments
inline fun run1<T>(body : fun() : T) : T = body()
fun main1(args : Array<String>) {
run1 @l{ 1 } // should not be an error
}
@@ -0,0 +1,13 @@
class N() : java.util.ArrayList<String>() {
override fun add(el: String) : Boolean {
super.add(el)
return super.add(el + el)
}
}
fun box(): String {
val n = N()
n.add("239")
if (n.get(0) == "239" && n.get(1) == "239239") return "OK";
return "fail";
}
@@ -0,0 +1,22 @@
open class M() {
open var b: Int = 0
}
class N() : M() {
val a : Int
get() {
super.b = super.b + 1
return super.b + 1
}
override var b: Int = a + 1
val superb : Int
get() = super.b
}
fun box(): String {
val n = N()
System.out?.println("a: " + n.a + " b: " + n.b + " superb: " + n.superb)
if (n.b == 3 && n.a == 4 && n.superb == 3) return "OK";
return "fail";
}
@@ -0,0 +1,29 @@
trait M {
var backingB : Int
var b : Int
get() = backingB
set(value: Int) {
backingB = value
}
}
class N() : M {
override var backingB : Int = 0
val a : Int
get() {
super.b = super.b + 1
return super.b + 1
}
override var b: Int = a + 1
val superb : Int
get() = super.b
}
fun box(): String {
val n = N()
System.out?.println("a: " + n.a + " b: " + n.b + " superb: " + n.superb)
if (n.b == 3 && n.a == 4 && n.superb == 3) return "OK";
return "fail";
}
@@ -16,7 +16,7 @@ import java.util.List;
* @author abreslav
*/
public abstract class JetTestCaseBuilder {
private static FilenameFilter emptyFilter = new FilenameFilter() {
public static FilenameFilter emptyFilter = new FilenameFilter() {
@Override
public boolean accept(File file, String name) {
return true;
@@ -43,6 +43,11 @@ public abstract class JetTestCaseBuilder {
@NotNull
public static TestSuite suiteForDirectory(String baseDataDir, @NotNull final String dataPath, boolean recursive, final FilenameFilter filter, @NotNull NamedTestFactory factory) {
TestSuite suite = new TestSuite(dataPath);
appendTestsInDirectory(baseDataDir, dataPath, recursive, filter, factory, suite);
return suite;
}
public static void appendTestsInDirectory(String baseDataDir, String dataPath, boolean recursive, final FilenameFilter filter, NamedTestFactory factory, TestSuite suite) {
final String extensionJet = ".jet";
final String extensionKt = ".kt";
final FilenameFilter extensionFilter = new FilenameFilter() {
@@ -76,7 +81,7 @@ public abstract class JetTestCaseBuilder {
List<File> subdirs = Arrays.asList(files);
Collections.sort(subdirs);
for (File subdir : subdirs) {
suite.addTest(suiteForDirectory(baseDataDir, dataPath + "/" + subdir.getName(), recursive, filter, factory));
appendTestsInDirectory(baseDataDir, dataPath + "/" + subdir.getName(), recursive, filter, factory, suite);
}
}
List<File> files = Arrays.asList(dir.listFiles(resultFilter));
@@ -87,6 +92,5 @@ public abstract class JetTestCaseBuilder {
String extension = fileName.endsWith(extensionJet) ? extensionJet : extensionKt;
suite.addTest(factory.createTest(dataPath, fileName.substring(0, fileName.length() - extension.length())));
}
return suite;
}
}
@@ -98,7 +98,7 @@ public abstract class CodegenTestCase extends JetLiteFixture {
}
protected String generateToText() {
GenerationState state = new GenerationState(getProject(), true);
GenerationState state = new GenerationState(getProject(), ClassBuilderFactory.TEXT);
AnalyzingUtils.checkForSyntacticErrors(myFile);
state.compile(myFile);
@@ -152,7 +152,7 @@ public abstract class CodegenTestCase extends JetLiteFixture {
protected ClassFileFactory generateClassesInFile() {
try {
GenerationState state = new GenerationState(getProject(), false);
GenerationState state = new GenerationState(getProject(), ClassBuilderFactory.BINARIES);
AnalyzingUtils.checkForSyntacticErrors(myFile);
state.compile(myFile);
@@ -80,4 +80,55 @@ public class FunctionGenTest extends CodegenTestCase {
public void testKt395 () {
blackBoxFile("regressions/kt395.jet");
}
/*
public void testFunction () throws InvocationTargetException, IllegalAccessException {
loadText("fun Any.foo() : fun(): String {\n" +
" return { \"239\" + this }\n" +
"}\n" +
"fun box() : String {\n" +
" return if((10.foo())() == \"23910\") \"OK\" else \"fail\"" +
"}" +
"");
System.out.println(generateToText());
Method foo = generateFunction();
assertTrue((Boolean) foo.invoke(null, "lala"));
assertFalse((Boolean) foo.invoke(null, "mama"));
}
fun Any.foo() : fun() : Unit {
return {}
}
fun Any.foo1() : fun(i : Int) : Unit {
return {}
}
fun foo2() : fun(i : fun()) : Unit {
return {}
}
fun fooT1<T>(t : T) : fun() : T {
return {t}
}
fun fooT2<T>() : fun(t : T) : T {
return {it}
}
fun main(args : Array<String>) {
args.foo()()
args.foo1()(1)
foo2()({})
(foo2()){}
val a = fooT1(1)()
a : Int
val b = fooT2<Int>()(1)
b : Int
fooT2()(1) // : Any?
}
*/
}
@@ -0,0 +1,18 @@
package org.jetbrains.jet.codegen;
public class SuperGenTest extends CodegenTestCase {
public void testBasicProperty () {
blackBoxFile("/super/basicproperty.jet");
System.out.println(generateToText());
}
public void testTraitProperty () {
blackBoxFile("/super/traitproperty.jet");
System.out.println(generateToText());
}
public void testBasicMethod () {
blackBoxFile("/super/basicmethod.jet");
System.out.println(generateToText());
}
}
@@ -6,6 +6,15 @@ import junit.framework.TestCase;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.parsing.JetParsingTest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
/**
* @author yole
*/
@@ -23,8 +32,9 @@ public class CompileEnvironmentTest extends TestCase {
super.tearDown();
}
public void testSmoke() {
environment.setJavaRuntime(CompileEnvironment.findActiveRtJar());
public void testSmoke() throws IOException {
final File activeRtJar = CompileEnvironment.findRtJar(true);
environment.setJavaRuntime(activeRtJar);
environment.initializeKotlinRuntime();
final String testDataDir = JetParsingTest.getTestDataDir() + "/compiler/smoke/";
final IModuleSetBuilder setBuilder = environment.loadModuleScript(testDataDir + "Smoke.kts");
@@ -33,5 +43,23 @@ public class CompileEnvironmentTest extends TestCase {
final ClassFileFactory factory = environment.compileModule(moduleBuilder, testDataDir);
assertNotNull(factory);
assertNotNull(factory.asBytes("Smoke/namespace.class"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
CompileEnvironment.writeToJar(factory, baos, null, false);
JarInputStream is = new JarInputStream(new ByteArrayInputStream(baos.toByteArray()));
final List<String> entries = listEntries(is);
assertTrue(entries.contains("Smoke/namespace.class"));
}
private List<String> listEntries(JarInputStream is) throws IOException {
List<String> entries = new ArrayList<String>();
while (true) {
final JarEntry jarEntry = is.getNextJarEntry();
if (jarEntry == null) {
break;
}
entries.add(jarEntry.getName());
}
return entries;
}
}
+141
View File
@@ -0,0 +1,141 @@
import java.util.concurrent.Executors
import java.net.InetSocketAddress
import java.net.URLDecoder
import java.io.*
import org.jboss.netty.bootstrap.ServerBootstrap
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory
import org.jboss.netty.channel.*
import org.jboss.netty.handler.codec.http.*
import org.jboss.netty.handler.stream.ChunkedWriteHandler
import org.jboss.netty.handler.codec.frame.TooLongFrameException
import org.jboss.netty.buffer.ChannelBuffers
import org.jboss.netty.util.CharsetUtil
import org.jboss.netty.handler.codec.http.HttpResponseStatus.*
import netty.*
import jlstring.*
namespace jlstring {
fun String.replace(c: Char, by: Char) : String = (this as java.lang.String).replace(c, by) as String
fun String.contains(s: String) : Boolean = (this as java.lang.String).contains(s as java.lang.CharSequence)
fun java.lang.String.plus(s: Any?) : String = (this as String) + s.toString()
}
namespace netty {
fun ChannelPipeline.with(op: fun ChannelPipeline.() ) : ChannelPipeline {
this.op()
return this
}
fun HttpResponse.set(header: String, value: Any?) : Unit {
setHeader(header, value)
}
fun HttpResponse.setContent(content: Any?) : Unit {
setContent(ChannelBuffers.copiedBuffer(content.toString() as java.lang.String, CharsetUtil.UTF_8))
}
fun ChannelHandlerContext.sendError(status: HttpResponseStatus?) {
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, status)
response["Content-Type"] = "text/plain; charset=UTF-8"
response.setContent("Failure: " + status.toString() + "\r\n")
// Close the connection as soon as the error message is sent.
this.getChannel()?.write(response)?.addListener(ChannelFutureListener.CLOSE)
}
fun String.decodeURI(encoding : String) : String? {
try {
return URLDecoder.decode(this, encoding)
}
catch (e : UnsupportedEncodingException) {
return null
}
}
fun String.sanitizeUri() : String? {
val path = decodeURI("UTF-8") ?: decodeURI("ISO-8859-1")
if (path == null)
throw Error()
val localizedPath : String = path.replace('/', File.separatorChar)
return if (localizedPath.contains(File.separator + ".") ||
localizedPath.contains("." + File.separator) ||
localizedPath.startsWith(".") || endsWith("."))
null
else
localizedPath
}
class StandardPipelineFactory(val config: fun ChannelPipeline.():Unit) : ChannelPipelineFactory {
override fun getPipeline() : ChannelPipeline {
val pipeline = DefaultChannelPipeline().with {
addLast("decoder", HttpRequestDecoder())
addLast("aggregator", HttpChunkAggregator(65536))
addLast("encoder", HttpResponseEncoder())
addLast("chunkedWriter", ChunkedWriteHandler())
}
pipeline.config () // can not move it inside with{} because of codegen bug
return pipeline
}
}
fun ServerBootstrap.configPipeline(config: fun ChannelPipeline.(): Unit) =
setPipelineFactory(
StandardPipelineFactory(config)
)
}
fun main(args : Array<String>) {
val bootstrap = ServerBootstrap(
NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()
)
)
bootstrap.configPipeline {
addLast("handler", HttpStaticFileServerHandler(args[0]))
}
bootstrap.bind(InetSocketAddress(8080))
}
class HttpStaticFileServerHandler(val rootDir: String) : SimpleChannelUpstreamHandler() {
fun messageReceived(ctx : ChannelHandlerContext, e : MessageEvent) {
val request = e.getMessage() as HttpRequest
if (request.getMethod() != HttpMethod.GET) {
ctx.sendError(METHOD_NOT_ALLOWED);
return;
}
val path = request.getUri()?.sanitizeUri()
if (path == null) {
ctx.sendError(FORBIDDEN);
return;
}
val file = File(rootDir + File.separator + path)
if (file.isHidden() || !file.exists()) {
ctx.sendError(NOT_FOUND)
return
}
if (!file.isFile()) {
ctx.sendError(FORBIDDEN)
return
}
var raf = RandomAccessFile(file, "r")
val fileLength = raf.length()
val response = DefaultHttpResponse(HttpVersion.HTTP_1_1, OK)
response["Content-Length"] = fileLength
val ch = e.getChannel()
ch?.write(response)
ch?.write(DefaultFileRegion(raf.getChannel(), 0, fileLength))
}
}
@@ -16,6 +16,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.util.Chunk;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.codegen.ClassBuilderFactory;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
@@ -69,7 +70,7 @@ public class JetCompiler implements TranslatingCompiler {
public void run() {
VirtualFile[] allFiles = compileContext.getCompileScope().getFiles(null, true);
GenerationState generationState = new GenerationState(compileContext.getProject(), false);
GenerationState generationState = new GenerationState(compileContext.getProject(), ClassBuilderFactory.BINARIES);
List<JetNamespace> namespaces = Lists.newArrayList();
for (VirtualFile virtualFile : allFiles) {
PsiFile psiFile = PsiManager.getInstance(compileContext.getProject()).findFile(virtualFile);
@@ -55,27 +55,27 @@ public class JetPsiCheckerTest extends LightDaemonAnalyzerTestCase {
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(JetTestCaseBuilder.suiteForDirectory(PluginTestCaseBase.getTestDataPathBase(), "/checker/", false, new JetTestCaseBuilder.NamedTestFactory() {
JetTestCaseBuilder.appendTestsInDirectory(PluginTestCaseBase.getTestDataPathBase(), "/checker/", false, JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name);
}
}));
suite.addTest(JetTestCaseBuilder.suiteForDirectory(PluginTestCaseBase.getTestDataPathBase(), "/checker/regression/", false, new JetTestCaseBuilder.NamedTestFactory() {
}, suite);
JetTestCaseBuilder.appendTestsInDirectory(PluginTestCaseBase.getTestDataPathBase(), "/checker/regression/", false, JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name);
}
}));
suite.addTest(JetTestCaseBuilder.suiteForDirectory(PluginTestCaseBase.getTestDataPathBase(), "/checker/infos/", false, new JetTestCaseBuilder.NamedTestFactory() {
}, suite);
JetTestCaseBuilder.appendTestsInDirectory(PluginTestCaseBase.getTestDataPathBase(), "/checker/infos/", false, JetTestCaseBuilder.emptyFilter, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name).setCheckInfos(true);
}
}));
}, suite);
return suite;
}
}
+1 -4
View File
@@ -13,10 +13,7 @@ namespace io {
fun print(message : Float) { System.out?.print(message) }
fun print(message : Double) { System.out?.print(message) }
fun println(message : Any?) {
System.out?.println(message)
}
fun println(message : Any?) { System.out?.println(message) }
fun println(message : Int) { System.out?.println(message) }
fun println(message : Long) { System.out?.println(message) }
fun println(message : Byte) { System.out?.println(message) }