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

This commit is contained in:
svtk
2011-10-24 18:54:35 +04:00
94 changed files with 1561 additions and 263 deletions
@@ -277,14 +277,17 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(begin);
v.load(iteratorVar, asmIterType);
FunctionDescriptor hND;
if(hasNextDescriptor instanceof FunctionDescriptor) {
hND = (FunctionDescriptor) hasNextDescriptor;
FunctionDescriptor hND = (FunctionDescriptor) hasNextDescriptor;
invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
}
else {
hND = ((PropertyDescriptor) hasNextDescriptor).getGetter();
// hND = ((PropertyDescriptor) hasNextDescriptor).getGetter();
// if(hND != null)
// invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
// else
intermediateValueForProperty((PropertyDescriptor) hasNextDescriptor, false, false).put(Type.BOOLEAN_TYPE, v);
}
invokeFunctionNoParams(hND, Type.BOOLEAN_TYPE, v);
v.ifeq(end);
myMap.enter(parameterDescriptor, asmParamType.getSize());
@@ -598,8 +601,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
for (DeclarationDescriptor descriptor : closureCodegen.closure.keySet()) {
final Type sharedVarType = getSharedVarType(descriptor);
consArgTypes.add(sharedVarType != null ? sharedVarType : state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType()));
Type sharedVarType = getSharedVarType(descriptor);
if(sharedVarType == null)
sharedVarType = state.getTypeMapper().mapType(((VariableDescriptor) descriptor).getOutType());
consArgTypes.add(sharedVarType);
final EnclosedValueDescriptor valueDescriptor = closureCodegen.closure.get(descriptor);
valueDescriptor.getOuterValue().put(sharedVarType, v);
}
@@ -1462,7 +1467,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return StackValue.onStack(Type.BOOLEAN_TYPE);
}
private StackValue generateEqualsForExpressionsOnStack(IElementType opToken, Type leftType, Type rightType, boolean leftNullable, boolean rightNullable) {
public StackValue generateEqualsForExpressionsOnStack(IElementType opToken, Type leftType, Type rightType, boolean leftNullable, boolean rightNullable) {
if (isNumberPrimitive(leftType) && leftType == rightType) {
return compareExpressionsOnStack(opToken, leftType);
}
@@ -342,7 +342,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
Map<DeclarationDescriptor, EnclosedValueDescriptor> closure = context.closure.closure;
int k = 0;
for (DeclarationDescriptor varDescr : closure.keySet()) {
final Type sharedVarType = context.closure.exprContext.getSharedVarType(varDescr);
Type sharedVarType = context.closure.exprContext.getSharedVarType(varDescr);
if(sharedVarType == null) {
sharedVarType = state.getTypeMapper().mapType(((VariableDescriptor) varDescr).getOutType());
}
iv.load(0, JetTypeMapper.TYPE_OBJECT);
iv.load(firstClosureIndex + k, StackValue.refType(sharedVarType));
iv.putfield(state.getTypeMapper().jvmName(descriptor, OwnerKind.IMPLEMENTATION), "$" + (k+1), sharedVarType.getDescriptor());
@@ -39,6 +39,7 @@ public class JetTypeMapper {
public static final Type JL_BOOLEAN_TYPE = Type.getObjectType("java/lang/Boolean");
public static final Type JL_NUMBER_TYPE = Type.getObjectType("java/lang/Number");
public static final Type JL_STRING_BUILDER = Type.getObjectType("java/lang/StringBuilder");
public static final Type JL_STRING_TYPE = Type.getObjectType("java/lang/String");
public static final Type ARRAY_INT_TYPE = Type.getType(int[].class);
public static final Type ARRAY_LONG_TYPE = Type.getType(long[].class);
@@ -59,15 +60,15 @@ public class JetTypeMapper {
public static final Type TYPE_FUNCTION1 = Type.getObjectType("jet/Function1");
public static final Type TYPE_ITERATOR = Type.getObjectType("jet/Iterator");
public static final Type TYPE_INT_RANGE = Type.getObjectType("jet/IntRange");
public static final Type TYPE_SHARED_VAR = Type.getObjectType("jet/refs/SharedVar$Object");
public static final Type TYPE_SHARED_INT = Type.getObjectType("jet/refs/SharedVar$Int");
public static final Type TYPE_SHARED_DOUBLE = Type.getObjectType("jet/refs/SharedVar$Double");
public static final Type TYPE_SHARED_FLOAT = Type.getObjectType("jet/refs/SharedVar$Float");
public static final Type TYPE_SHARED_BYTE = Type.getObjectType("jet/refs/SharedVar$Byte");
public static final Type TYPE_SHARED_SHORT = Type.getObjectType("jet/refs/SharedVar$Short");
public static final Type TYPE_SHARED_CHAR = Type.getObjectType("jet/refs/SharedVar$Char");
public static final Type TYPE_SHARED_LONG = Type.getObjectType("jet/refs/SharedVar$Long");
public static final Type TYPE_SHARED_BOOLEAN = Type.getObjectType("jet/refs/SharedVar$Boolean");
public static final Type TYPE_SHARED_VAR = Type.getObjectType("jet/runtime/SharedVar$Object");
public static final Type TYPE_SHARED_INT = Type.getObjectType("jet/runtime/SharedVar$Int");
public static final Type TYPE_SHARED_DOUBLE = Type.getObjectType("jet/runtime/SharedVar$Double");
public static final Type TYPE_SHARED_FLOAT = Type.getObjectType("jet/runtime/SharedVar$Float");
public static final Type TYPE_SHARED_BYTE = Type.getObjectType("jet/runtime/SharedVar$Byte");
public static final Type TYPE_SHARED_SHORT = Type.getObjectType("jet/runtime/SharedVar$Short");
public static final Type TYPE_SHARED_CHAR = Type.getObjectType("jet/runtime/SharedVar$Char");
public static final Type TYPE_SHARED_LONG = Type.getObjectType("jet/runtime/SharedVar$Long");
public static final Type TYPE_SHARED_BOOLEAN = Type.getObjectType("jet/runtime/SharedVar$Boolean");
public JetTypeMapper(JetStandardLibrary standardLibrary, BindingContext bindingContext) {
this.standardLibrary = standardLibrary;
@@ -460,7 +461,10 @@ public class JetTypeMapper {
parameterTypes.add(type);
}
for (ValueParameterDescriptor parameter : parameters) {
final Type type = mapType(parameter.getOutType());
Type type = mapType(parameter.getOutType());
if(parameter.isVararg()) {
type = Type.getType("[" + type.getDescriptor());
}
valueParameterTypes.add(type);
parameterTypes.add(type);
}
@@ -558,7 +562,13 @@ public class JetTypeMapper {
parameterTypes.add(mapType(receiver.getType()));
}
for (ValueParameterDescriptor parameter : parameters) {
parameterTypes.add(mapType(parameter.getOutType()));
if(parameter.isVararg()) {
Type type = mapType(parameter.getOutType());
type = Type.getType("[" + type.getDescriptor());
parameterTypes.add(type);
}
else
parameterTypes.add(mapType(parameter.getOutType()));
}
Type returnType = mapReturnType(f.getReturnType());
return new Method(name, returnType, parameterTypes.toArray(new Type[parameterTypes.size()]));
@@ -31,31 +31,31 @@ public class ArrayIterator implements IntrinsicMethod {
JetStandardLibrary standardLibrary = codegen.getState().getStandardLibrary();
if(containingDeclaration.equals(standardLibrary.getArray())) {
codegen.generateTypeInfo(funDescriptor.getReturnType().getArguments().get(0).getType());
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([Ljava/lang/Object;Ljet/typeinfo/TypeInfo;)Ljet/Iterator;");
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([Ljava/lang/Object;Ljet/typeinfo/TypeInfo;)Ljet/Iterator;");
}
else if(containingDeclaration.equals(standardLibrary.getByteArrayClass())) {
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([B)Ljet/Iterator;");
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([B)Ljet/Iterator;");
}
else if(containingDeclaration.equals(standardLibrary.getShortArrayClass())) {
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([S)Ljet/Iterator;");
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([S)Ljet/Iterator;");
}
else if(containingDeclaration.equals(standardLibrary.getIntArrayClass())) {
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([I)Ljet/Iterator;");
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([I)Ljet/Iterator;");
}
else if(containingDeclaration.equals(standardLibrary.getLongArrayClass())) {
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([J)Ljet/Iterator;");
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([J)Ljet/Iterator;");
}
else if(containingDeclaration.equals(standardLibrary.getFloatArrayClass())) {
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([F)Ljet/Iterator;");
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([F)Ljet/Iterator;");
}
else if(containingDeclaration.equals(standardLibrary.getDoubleArrayClass())) {
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([D)Ljet/Iterator;");
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([D)Ljet/Iterator;");
}
else if(containingDeclaration.equals(standardLibrary.getCharArrayClass())) {
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([C)Ljet/Iterator;");
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([C)Ljet/Iterator;");
}
else if(containingDeclaration.equals(standardLibrary.getBooleanArrayClass())) {
v.invokestatic("jet/arrays/ArrayIterator", "iterator", "([Z)Ljet/Iterator;");
v.invokestatic("jet/runtime/ArrayIterator", "iterator", "([Z)Ljet/Iterator;");
}
else {
throw new UnsupportedOperationException(containingDeclaration.toString());
@@ -0,0 +1,43 @@
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetCallExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lexer.JetTokens;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
/**
* @author alex.tkachman
*/
public class Equals implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
boolean leftNullable = true;
if(element instanceof JetCallExpression) {
JetCallExpression jetCallExpression = (JetCallExpression) element;
JetExpression calleeExpression = jetCallExpression.getCalleeExpression();
if(calleeExpression != null) {
JetType leftType = codegen.getBindingContext().get(BindingContext.EXPRESSION_TYPE, calleeExpression);
if(leftType != null)
leftNullable = leftType.isNullable();
}
}
JetExpression rightExpr = arguments.get(0);
JetType rightType = codegen.getBindingContext().get(BindingContext.EXPRESSION_TYPE, rightExpr);
codegen.gen(rightExpr).put(JetTypeMapper.TYPE_OBJECT, v);
return codegen.generateEqualsForExpressionsOnStack(JetTokens.EQEQ, JetTypeMapper.TYPE_OBJECT, JetTypeMapper.TYPE_OBJECT, leftNullable, rightType.isNullable());
}
}
@@ -73,6 +73,11 @@ public class IntrinsicMethods {
declareIntrinsicFunction("String", "plus", 1, new Concat());
declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString());
declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, new Equals());
// declareIntrinsicFunction("Any", "equals", 1, new Equals());
//
declareIntrinsicStringMethods();
declareIntrinsicProperty("String", "length", new StringLength());
@@ -0,0 +1,24 @@
package org.jetbrains.jet.codegen.intrinsics;
import com.intellij.psi.PsiElement;
import org.jetbrains.jet.codegen.ExpressionCodegen;
import org.jetbrains.jet.codegen.JetTypeMapper;
import org.jetbrains.jet.codegen.StackValue;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
import java.util.List;
/**
* @author alex.tkachman
*/
public class ToString implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
v.invokestatic("java/lang/String", "valueOf", "(Ljava/lang/Object;)Ljava/lang/String;");
return StackValue.onStack(JetTypeMapper.JL_STRING_TYPE);
}
}
@@ -1,6 +1,6 @@
package org.jetbrains.jet.cli;
import com.google.common.collect.Lists;
import com.google.common.collect.*;
import com.intellij.core.JavaCoreEnvironment;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
@@ -8,10 +8,15 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.sampullara.cli.Args;
import com.sampullara.cli.Argument;
import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange;
import org.jetbrains.jet.lang.diagnostics.Severity;
import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespace;
@@ -24,16 +29,30 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.List;
/**
* @author yole
* @author alex.tkachman
*/
public class KotlinCompiler {
public static class Arguments {
@Argument(value = "output", description = "output directory")
public String outputDir;
@Argument(value = "src", description = "source file or directory", required = true)
public String src;
}
public static void main(String[] args) {
System.setProperty("java.awt.headless", "true");
if (args.length < 1) {
System.out.println("Usage: KotlinCompiler <filename>");
Arguments arguments = new Arguments();
try {
Args.parse(arguments, args);
}
catch (Throwable t) {
System.out.println("Usage: KotlinCompiler -output <outputDir> -src <filename or dirname>");
t.printStackTrace();
return;
}
@@ -44,6 +63,119 @@ public class KotlinCompiler {
};
JavaCoreEnvironment environment = new JavaCoreEnvironment(root);
File rtJar = initJdk();
if (rtJar == null) return;
environment.addToClasspath(rtJar);
environment.registerFileType(JetFileType.INSTANCE, "kt");
environment.registerParserDefinition(new JetParserDefinition());
VirtualFile vFile = environment.getLocalFileSystem().findFileByPath(arguments.src);
if (vFile == null) {
System.out.print("File/directory not found: " + arguments.src);
return;
}
Project project = environment.getProject();
GenerationState generationState = new GenerationState(project, false);
List<JetNamespace> namespaces = Lists.newArrayList();
if(vFile.isDirectory()) {
File dir = new File(vFile.getPath());
addFiles(environment, project, namespaces, dir);
}
else {
PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile);
if (psiFile instanceof JetFile) {
namespaces.add(((JetFile) psiFile).getRootNamespace());
}
else {
System.out.print("Not a Kotlin file: " + vFile.getPath());
return;
}
}
BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(project, namespaces, JetControlFlowDataTraceFactory.EMPTY);
ErrorCollector errorCollector = new ErrorCollector(bindingContext);
errorCollector.report();
if (!errorCollector.hasErrors) {
generationState.compileCorrectNamespaces(bindingContext, namespaces);
final ClassFileFactory factory = generationState.getFactory();
if(arguments.outputDir == null) {
System.out.println("Output directory is not specified - no files will be saved to the disk");
}
else {
List<String> files = factory.files();
for (String file : files) {
File target = new File(arguments.outputDir, file);
try {
FileUtil.writeToFile(target, factory.asBytes(file));
System.out.println("Generated classfile: " + target);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
}
}
private static class ErrorCollector {
Multimap<PsiFile,DiagnosticWithTextRange> maps = LinkedHashMultimap.<PsiFile, DiagnosticWithTextRange>create();
boolean hasErrors;
public ErrorCollector(BindingContext bindingContext) {
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
report(diagnostic);
}
}
private void report(Diagnostic diagnostic) {
hasErrors |= diagnostic.getSeverity() == Severity.ERROR;
if(diagnostic instanceof DiagnosticWithTextRange) {
DiagnosticWithTextRange diagnosticWithTextRange = (DiagnosticWithTextRange) diagnostic;
maps.put(diagnosticWithTextRange.getPsiFile(), diagnosticWithTextRange);
}
else {
System.out.println(diagnostic.getSeverity().toString() + ": " + diagnostic.getMessage());
}
}
void report() {
if(!maps.isEmpty()) {
for (PsiFile psiFile : maps.keySet()) {
System.out.println(psiFile.getVirtualFile().getPath());
Collection<DiagnosticWithTextRange> diagnosticWithTextRanges = maps.get(psiFile);
for (DiagnosticWithTextRange diagnosticWithTextRange : diagnosticWithTextRanges) {
String position = DiagnosticUtils.formatPosition(diagnosticWithTextRange);
System.out.println("\t" + diagnosticWithTextRange.getSeverity().toString() + ": " + position + " " + diagnosticWithTextRange.getMessage());
}
}
}
}
}
private static void addFiles(JavaCoreEnvironment environment, Project project, List<JetNamespace> namespaces, File dir) {
for(File file : dir.listFiles()) {
if(!file.isDirectory()) {
VirtualFile virtualFile = environment.getLocalFileSystem().findFileByPath(file.getAbsolutePath());
PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile);
if (psiFile instanceof JetFile) {
namespaces.add(((JetFile) psiFile).getRootNamespace());
}
}
else {
addFiles(environment, project, namespaces, file);
}
}
}
private static File initJdk() {
String javaHome = System.getenv("JAVA_HOME");
File rtJar = null;
if (javaHome == null) {
@@ -66,7 +198,7 @@ public class KotlinCompiler {
if(rtJar == null) {
System.out.println("JAVA_HOME environment variable needs to be defined");
return;
return null;
}
}
else {
@@ -75,70 +207,9 @@ public class KotlinCompiler {
if (rtJar == null || !rtJar.exists()) {
System.out.print("No rt.jar found under JAVA_HOME=" + javaHome);
return;
return null;
}
environment.addToClasspath(rtJar);
environment.registerFileType(JetFileType.INSTANCE, "kt");
environment.registerFileType(JetFileType.INSTANCE, "jet");
environment.registerParserDefinition(new JetParserDefinition());
VirtualFile vFile = environment.getLocalFileSystem().findFileByPath(args [0]);
if (vFile == null) {
System.out.print("File not found: " + args[0]);
return;
}
Project project = environment.getProject();
GenerationState generationState = new GenerationState(project, false);
List<JetNamespace> namespaces = Lists.newArrayList();
PsiFile psiFile = PsiManager.getInstance(project).findFile(vFile);
if (psiFile instanceof JetFile) {
namespaces.add(((JetFile) psiFile).getRootNamespace());
}
else {
System.out.print("Not a Kotlin file: " + vFile.getPath());
return;
}
BindingContext bindingContext = AnalyzingUtils.getInstance(JavaDefaultImports.JAVA_DEFAULT_IMPORTS).analyzeNamespaces(project, namespaces, JetControlFlowDataTraceFactory.EMPTY);
boolean errors = false;
for (Diagnostic diagnostic : bindingContext.getDiagnostics()) {
switch (diagnostic.getSeverity()) {
case ERROR:
errors = true;
report(diagnostic);
break;
case INFO:
report(diagnostic);
break;
case WARNING:
report(diagnostic);
break;
}
}
if (!errors) {
generationState.compileCorrectNamespaces(bindingContext, namespaces);
final ClassFileFactory factory = generationState.getFactory();
List<String> files = factory.files();
for (String file : files) {
File target = new File(vFile.getParent().getPath(), file);
try {
FileUtil.writeToFile(target, factory.asBytes(file));
System.out.println("Generated classfile: " + target);
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
}
private static void report(Diagnostic diagnostic) {
System.out.println(diagnostic.getMessage());
return rtJar;
}
private static File findRtJar(String javaHome) {
@@ -20,4 +20,7 @@ public class JavaDefaultImports {
rootScope.importScope(new JavaPackageScope("java.lang", null, javaSemanticServices));
}
};
private JavaDefaultImports() {
}
}
+2 -2
View File
@@ -41,8 +41,8 @@ fun Any?.equals(other : Any?) : Boolean// = this === other
fun Any?.toString() : String// = this === other
trait Iterator<out T> {
fun next() : T
fun hasNext() : Boolean
fun next() : T
val hasNext : Boolean
}
trait Iterable<out T> {
@@ -63,4 +63,22 @@ public class DiagnosticUtils {
return "' at offset " + offset + " (line unknown)" + pathSuffix;
}
}
public static String formatPosition(DiagnosticWithTextRange diagnosticWithTextRange) {
PsiFile file = diagnosticWithTextRange.getPsiFile();
Document document = file.getViewProvider().getDocument();
String position;
int offset = diagnosticWithTextRange.getTextRange().getStartOffset();
if (document != null) {
int lineNumber = document.getLineNumber(offset);
int lineStartOffset = document.getLineStartOffset(lineNumber);
int column = offset - lineStartOffset;
position = "(" + (lineNumber + 1) + "," + column + ")";
}
else {
position = "(offset: " + offset + " line unknown)";
}
return position;
}
}
@@ -1429,7 +1429,7 @@ public class JetParsing extends AbstractJetParsing {
/*
* functionType
* : "fun" (type ".")? functionTypeContents
* : "fun" (type ".")? "(" (parameter | modifiers type){","} ")" (":" type)? // Unit by default
* ;
*/
private void parseFunctionType() {
@@ -1446,22 +1446,15 @@ public class JetParsing extends AbstractJetParsing {
advance(); // DOT
}
parseFunctionTypeContents();
functionType.done(FUNCTION_TYPE);
}
/*
* functionTypeContents
* : "(" (parameter | type){","} ")" ":" type
* ;
*/
private void parseFunctionTypeContents() {
parseValueParameterList(true, TokenSet.EMPTY);
expect(COLON, "Expecting ':' followed by a return type", TYPE_REF_FIRST);
if (at(COLON)) {
advance(); // COLON // expect(COLON, "Expecting ':' followed by a return type", TYPE_REF_FIRST);
parseTypeRef();
parseTypeRef();
}
functionType.done(FUNCTION_TYPE);
}
/*
@@ -70,6 +70,11 @@ public class DelegatingBindingTrace implements BindingTrace {
}
}
public void clear() {
map.clear();
diagnostics.clear();
}
@Override
public void report(@NotNull Diagnostic diagnostic) {
diagnostics.add(diagnostic);
@@ -11,6 +11,7 @@ public class TemporaryBindingTrace extends DelegatingBindingTrace {
private final BindingTrace trace;
private TemporaryBindingTrace(BindingTrace trace) {
super(trace.getBindingContext());
this.trace = trace;
@@ -18,5 +19,6 @@ public class TemporaryBindingTrace extends DelegatingBindingTrace {
public void commit() {
addAllMyDataTo(trace);
clear();
}
}
@@ -105,12 +105,9 @@ public class TypeResolver {
}
else {
if (actualArgumentCount != expectedArgumentCount) {
// String errorMessage = (expectedArgumentCount == 0 ? "No" : expectedArgumentCount) + " type arguments expected";
if (actualArgumentCount == 0) {
// trace.getErrorHandler().genericError(type.getNode(), errorMessage);
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type, expectedArgumentCount));
} else {
// trace.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type.getTypeArgumentList(), expectedArgumentCount));
}
} else {
@@ -160,10 +157,14 @@ public class TypeResolver {
}
JetTypeReference returnTypeRef = type.getReturnTypeRef();
JetType returnType;
if (returnTypeRef != null) {
JetType returnType = resolveType(scope, returnTypeRef);
result[0] = JetStandardClasses.getFunctionType(annotations, receiverType, parameterTypes, returnType);
returnType = resolveType(scope, returnTypeRef);
}
else {
returnType = JetStandardClasses.getUnitType();
}
result[0] = JetStandardClasses.getFunctionType(annotations, receiverType, parameterTypes, returnType);
}
@Override
@@ -206,8 +206,6 @@ public class CallResolver {
@NotNull JetType expectedType,
@NotNull final List<ResolutionTask<D>> prioritizedTasks, // high to low priority
@NotNull final JetReferenceExpression reference) {
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
OverloadResolutionResults<D> resultsForFirstNonemptyCandidateSet = null;
TracingStrategy tracing = new TracingStrategy() {
@Override
public <D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCallImpl<D> resolvedCall) {
@@ -272,12 +270,12 @@ public class CallResolver {
}
@Override
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Set<ResolvedCallImpl<D>> descriptors) {
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {
trace.report(OVERLOAD_RESOLUTION_AMBIGUITY.on(call.getCallNode(), descriptors));
}
@Override
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<ResolvedCallImpl<D>> descriptors) {
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {
trace.report(NONE_APPLICABLE.on(reference, descriptors));
}
@@ -323,6 +321,9 @@ public class CallResolver {
trace.report(UNNECESSARY_SAFE_CALL.on((JetElement) callOperationNode.getTreeParent().getPsi(), callOperationNode, type));
}
};
TemporaryBindingTrace traceForFirstNonemptyCandidateSet = null;
OverloadResolutionResults<D> resultsForFirstNonemptyCandidateSet = null;
for (ResolutionTask<D> task : prioritizedTasks) {
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
OverloadResolutionResults<D> results = performResolution(temporaryTrace, scope, expectedType, task, tracing);
@@ -479,6 +480,14 @@ public class CallResolver {
task.performAdvancedChecks(candidate, temporaryTrace, tracing);
// 'super' cannot be passed as an argument, for receiver arguments expression typer does not track this
// See TaskPrioritizer for more
JetSuperExpression superExpression = TaskPrioritizer.getReceiverSuper(candidateCall.getReceiverArgument());
if (superExpression != null) {
temporaryTrace.report(SUPER_IS_NOT_AN_EXPRESSION.on(superExpression, superExpression.getText()));
candidateCall.setStatus(OTHER_ERROR);
}
recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
}
@@ -540,21 +549,6 @@ public class CallResolver {
}
}
// private <D extends CallableDescriptor> Function<ValueParameterDescriptor, ValueParameterDescriptor> createMapFunction(D substitutedFunctionDescriptor) {
// assert substitutedFunctionDescriptor != null;
// final Map<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap = Maps.newHashMap();
// for (ValueParameterDescriptor valueParameterDescriptor : substitutedFunctionDescriptor.getValueParameters()) {
// parameterMap.put(valueParameterDescriptor.getOriginal(), valueParameterDescriptor);
// }
//
// return new Function<ValueParameterDescriptor, ValueParameterDescriptor>() {
// @Override
// public ValueParameterDescriptor apply(ValueParameterDescriptor input) {
// return parameterMap.get(input.getOriginal());
// }
// };
// }
private <D extends CallableDescriptor> void replaceValueParametersWithSubstitutedOnes(ResolvedCallImpl<D> candidateCall, @NotNull D substitutedDescriptor) {
Map<ValueParameterDescriptor, ValueParameterDescriptor> parameterMap = Maps.newHashMap();
for (ValueParameterDescriptor valueParameterDescriptor : substitutedDescriptor.getValueParameters()) {
@@ -656,30 +650,47 @@ public class CallResolver {
Set<ResolvedCallImpl<D>> successfulCandidates,
Set<ResolvedCallImpl<D>> failedCandidates) {
// TODO : maybe it's better to filter overrides out first, and only then look for the maximally specific
if (successfulCandidates.size() > 0) {
return chooseAndReportMaximallySpecific(trace, tracing, successfulCandidates);
OverloadResolutionResults<D> results = chooseAndReportMaximallySpecific(successfulCandidates);
if (results.isAmbiguity()) {
// This check is needed for the following case:
// x.foo(unresolved) -- if there are multiple foo's, we'd report an ambiguity, and it does not make sense here
if (allClean(results.getResults())) {
tracing.ambiguity(trace, results.getResults());
}
tracing.recordAmbiguity(trace, results.getResults());
}
return results;
}
else if (!failedCandidates.isEmpty()) {
if (failedCandidates.size() != 1) {
Set<ResolvedCallImpl<D>> weakErrors = Sets.newLinkedHashSet();
for (ResolvedCallImpl<D> candidate : failedCandidates) {
if (candidate.getStatus().isWeakError()) {
weakErrors.add(candidate);
}
}
if (!weakErrors.isEmpty()) {
OverloadResolutionResults<D> results = chooseAndReportMaximallySpecific(trace, tracing, weakErrors);
if (results.isSuccess()) {
return OverloadResolutionResults.singleFailedCandidate(results.getResult());
// This is needed when there are several overloads some of which are OK but for nullability of the receiver,
// and some are not OK at all. In this case we'd like to say "unsafe call" rather than "none applicable"
// Used to be: weak errors. Generalized for future extensions
for (EnumSet<ResolutionStatus> severityLevel : SEVERITY_LEVELS) {
Set<ResolvedCallImpl<D>> thisLevel = Sets.newLinkedHashSet();
for (ResolvedCallImpl<D> candidate : failedCandidates) {
if (severityLevel.contains(candidate.getStatus())) {
thisLevel.add(candidate);
}
}
if (!thisLevel.isEmpty()) {
OverloadResolutionResults<D> results = chooseAndReportMaximallySpecific(thisLevel);
if (results.isSuccess()) {
results.getResult().getTrace().commit();
return OverloadResolutionResults.singleFailedCandidate(results.getResult());
}
return OverloadResolutionResults.manyFailedCandidates(results.getResults());
tracing.noneApplicable(trace, results.getResults());
tracing.recordAmbiguity(trace, results.getResults());
return OverloadResolutionResults.manyFailedCandidates(results.getResults());
}
}
assert false : "Should not be reachable, cause every status must belong to some level";
Set<ResolvedCallImpl<D>> noOverrides = OverridingUtil.filterOverrides(failedCandidates, MAP_TO_CANDIDATE);
if (noOverrides.size() != 1) {
// tracing.reportOverallResolutionError(trace, "None of the following functions can be called with the arguments supplied: "
// + makeErrorMessageForMultipleDescriptors(noOverrides));
tracing.noneApplicable(trace, noOverrides);
tracing.recordAmbiguity(trace, noOverrides);
return OverloadResolutionResults.manyFailedCandidates(noOverrides);
@@ -696,15 +707,20 @@ public class CallResolver {
}
}
private <D extends CallableDescriptor> OverloadResolutionResults<D> chooseAndReportMaximallySpecific(BindingTrace trace, TracingStrategy tracing, Set<ResolvedCallImpl<D>> candidates) {
private <D extends CallableDescriptor> boolean allClean(Collection<ResolvedCallImpl<D>> results) {
for (ResolvedCallImpl<D> result : results) {
if (result.isDirty()) return false;
}
return true;
}
private <D extends CallableDescriptor> OverloadResolutionResults<D> chooseAndReportMaximallySpecific(Set<ResolvedCallImpl<D>> candidates) {
if (candidates.size() != 1) {
Set<ResolvedCallImpl<D>> cleanCandidates = Sets.newLinkedHashSet(candidates);
boolean allClean = true;
for (Iterator<ResolvedCallImpl<D>> iterator = cleanCandidates.iterator(); iterator.hasNext(); ) {
ResolvedCallImpl<D> candidate = iterator.next();
if (candidate.isDirty()) {
iterator.remove();
allClean = false;
}
}
@@ -722,13 +738,6 @@ public class CallResolver {
}
Set<ResolvedCallImpl<D>> noOverrides = OverridingUtil.filterOverrides(candidates, MAP_TO_RESULT);
if (allClean) {
// tracing.reportOverallResolutionError(trace, "Overload resolution ambiguity: "
// + makeErrorMessageForMultipleDescriptors(noOverrides));
tracing.ambiguity(trace, noOverrides);
}
tracing.recordAmbiguity(trace, noOverrides);
return OverloadResolutionResults.ambiguity(noOverrides);
}
@@ -1,5 +1,7 @@
package org.jetbrains.jet.lang.resolve.calls;
import java.util.EnumSet;
/**
* @author abreslav
*/
@@ -9,7 +11,14 @@ public enum ResolutionStatus {
OTHER_ERROR,
SUCCESS(true);
@SuppressWarnings("unchecked")
public static final EnumSet<ResolutionStatus>[] SEVERITY_LEVELS = new EnumSet[] {
EnumSet.of(UNSAFE_CALL_ERROR), // weakest
EnumSet.of(OTHER_ERROR), // most severe
};
private final boolean success;
private int severityIndex = -1;
private ResolutionStatus(boolean success) {
this.success = success;
@@ -25,11 +34,21 @@ public enum ResolutionStatus {
public ResolutionStatus combine(ResolutionStatus other) {
if (this.isSuccess()) return other;
if (this.isWeakError() && !other.isSuccess()) return other;
if (!other.isSuccess() && this.getSeverityIndex() < other.getSeverityIndex()) return other;
return this;
}
private int getSeverityIndex() {
if (severityIndex == -1) {
for (int i = 0; i < SEVERITY_LEVELS.length; i++) {
if (SEVERITY_LEVELS[i].contains(this)) {
severityIndex = i;
break;
}
}
}
assert severityIndex >= 0;
public boolean isWeakError() {
return this == UNSAFE_CALL_ERROR;
return severityIndex;
}
}
@@ -2,16 +2,20 @@ package org.jetbrains.jet.lang.resolve.calls;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.psi.Call;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetSuperExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastService;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.JetTypeChecker;
@@ -72,6 +76,18 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
return false;
}
@Nullable
/*package*/ static JetSuperExpression getReceiverSuper(@NotNull ReceiverDescriptor receiver) {
if (receiver instanceof ExpressionReceiver) {
ExpressionReceiver expressionReceiver = (ExpressionReceiver) receiver;
JetExpression expression = expressionReceiver.getExpression();
if (expression instanceof JetSuperExpression) {
return (JetSuperExpression) expression;
}
}
return null;
}
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull Call call, @NotNull String name, @NotNull BindingContext bindingContext, @NotNull DataFlowInfo dataFlowInfo) {
List<ResolutionTask<D>> result = Lists.newArrayList();
@@ -108,8 +124,17 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
convertWithReceivers(membersForThisVariant, Collections.singletonList(variant), Collections.singletonList(NO_RECEIVER), members);
}
addTask(result, call, locals, dataFlowInfo);
addTask(result, call, members, dataFlowInfo);
if (getReceiverSuper(receiver) != null) {
// If the call is of the form super.foo(), it can actually be only a member
// But if there's no appropriate member, we would like to report that super cannot be a receiver for an extension
// Thus, put members first
addTask(result, call, members, dataFlowInfo);
addTask(result, call, locals, dataFlowInfo);
}
else {
addTask(result, call, locals, dataFlowInfo);
addTask(result, call, members, dataFlowInfo);
}
for (ReceiverDescriptor implicitReceiver : implicitReceivers) {
Collection<D> memberExtensions = getExtensionsByName(implicitReceiver.getType().getMemberScope(), name);
@@ -8,7 +8,6 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.JetType;
import java.util.Collection;
import java.util.Set;
/**
* @author abreslav
@@ -40,10 +39,10 @@ import java.util.Set;
public void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount) {}
@Override
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Set<ResolvedCallImpl<D>> descriptors) {}
public <D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {}
@Override
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<ResolvedCallImpl<D>> descriptors) {}
public <D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors) {}
@Override
public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {}
@@ -74,9 +73,9 @@ import java.util.Set;
void wrongNumberOfTypeArguments(@NotNull BindingTrace trace, int expectedTypeArgumentCount);
<D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Set<ResolvedCallImpl<D>> descriptors);
<D extends CallableDescriptor> void ambiguity(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors);
<D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Set<ResolvedCallImpl<D>> descriptors);
<D extends CallableDescriptor> void noneApplicable(@NotNull BindingTrace trace, @NotNull Collection<ResolvedCallImpl<D>> descriptors);
void instantiationOfAbstractClass(@NotNull BindingTrace trace);
@@ -8,4 +8,6 @@ public interface MutableSlicedMap extends SlicedMap {
<K, V> void put(WritableSlice<K, V> slice, K key, V value);
<K, V> V remove(RemovableSlice<K, V> slice, K key);
void clear();
}
@@ -47,6 +47,11 @@ public class SlicedMapImpl implements MutableSlicedMap {
slice.afterPut(this, key, value);
}
@Override
public void clear() {
map.clear();
}
@Override
public <K, V> V get(ReadOnlySlice<K, V> slice, K key) {
SlicedMapKey<K, V> slicedMapKey = slice.makeKey(key);
@@ -0,0 +1,21 @@
trait T {
fun foo() {}
fun buzz() {}
fun buzz1(i : Int) {}
}
fun T.bar() {}
fun T.buzz() {}
fun T.buzz1() {}
class C : T {
fun test() {
fun T.buzz() {}
fun T.buzz1() {}
super.foo() // OK
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.bar() // Error
super.buzz() // OK, resolved to a member
super.<!NO_VALUE_FOR_PARAMETER!>buzz1<!>() // Resolved to a member, but error: no parameter passed where required
}
}
@@ -1,5 +1,17 @@
namespace example;
fun any(a : Any) {}
fun notAnExpression() {
any(<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>) // not an expression
if (<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>) {} else {} // not an expression
val x = <!SUPER_IS_NOT_AN_EXPRESSION!>super<!> // not an expression
when (1) {
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!> => 1 // not an expression
}
}
trait T {
fun foo() {}
}
@@ -72,6 +84,6 @@ class ERROR<E>() : <!UNRESOLVED_REFERENCE!>UR<!> {
// No supertype at all
class A1 {
fun test() {
super.equals(null)
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.equals(null)
}
}
@@ -0,0 +1,3 @@
fun foo(f : fun()) {
val x : Unit = f()
}
@@ -0,0 +1,13 @@
trait Iterator<out T> {
fun next() : T
val hasNext : Boolean
fun <R> map(transform: fun(element: T) : R) : Iterator<R> =
object : Iterator<R> {
override fun next() : R = transform(<!NO_THIS!>this@map<!>.next())
override val hasNext : Boolean
// There's no 'this' associated with the map() function, only this of the Iterator class
get() = <!NO_THIS!>this@map<!>.hasNext
}
}
@@ -88,7 +88,8 @@ class MyCollection2(): Iterable<Int> {
var k : Int = 5
override fun next() : Int = k--
override fun hasNext() = k > 0
override val hasNext : Boolean
get() = k > 0
}
}
@@ -99,7 +100,8 @@ class MyCollection3() {
var k : Int = 5
fun next() : Int? = k--
fun hasNext() = k > 0
val hasNext : Boolean
get() = k > 0
}
}
+7
View File
@@ -0,0 +1,7 @@
// KT-156 Fix the this<Super> syntax
fun foo() {
super.foo();
super<Int>.foo();
super<>.foo();
super<Int>@label.foo();
}
+88
View File
@@ -0,0 +1,88 @@
JetFile: Super.jet
PsiComment(EOL_COMMENT)('// KT-156 Fix the this<Super> syntax')
PsiWhiteSpace('\n')
NAMESPACE
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(DOT)('.')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiElement(GT)('>')
PsiElement(DOT)('.')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
PsiErrorElement:Type expected
<empty list>
PsiElement(GT)('>')
PsiElement(DOT)('.')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n ')
DOT_QUALIFIED_EXPRESSION
SUPER_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(super)('super')
PsiElement(LT)('<')
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Int')
PsiElement(GT)('>')
LABEL_QUALIFIER
LABEL_REFERENCE
PsiElement(LABEL_IDENTIFIER)('@label')
PsiElement(DOT)('.')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiElement(SEMICOLON)(';')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
+36
View File
@@ -0,0 +1,36 @@
~T~trait T {
fun foo() {}
}
~C~open class C() {
fun bar() {}
}
~A~class A<E>() : C(), T {
fun test() {
`T`super<T>.foo()
`C`super<C>.bar()
`T`super<T>@A.foo()
`C`super<C>@A.bar()
}
class B : T {
fun test() {
`T`super<T>.foo();
`C`super<C>@A.bar()
`T`super<T>@A.foo()
`T`super<T>@B.foo()
`T`super.foo()
}
}
}
~G~trait G<T> {
fun foo() {}
}
class CG : G<Int> {
fun test() {
`G`super<`G`G>.foo() // OK
}
}
@@ -56,42 +56,42 @@ public class ArrayGenTest extends CodegenTestCase {
}
public void testIterator () throws Exception {
loadText("fun box() { val x = Array<Int>(5, { it } ).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
loadText("fun box() { val x = Array<Int>(5, { it } ).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testPrimitiveIterator () throws Exception {
loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
loadText("fun box() { val x = ByteArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testLongIterator () throws Exception {
loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
loadText("fun box() { val x = LongArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testCharIterator () throws Exception {
loadText("fun box() { val x = CharArray(5).iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
loadText("fun box() { val x = CharArray(5).iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testArrayIndices () throws Exception {
loadText("fun box() { val x = Array<Int>(5, {it}).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
loadText("fun box() { val x = Array<Int>(5, {it}).indices.iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
}
public void testCharIndices () throws Exception {
loadText("fun box() { val x = CharArray(5).indices.iterator(); while(x.hasNext()) { java.lang.System.out?.println(x.next()) } }");
loadText("fun box() { val x = CharArray(5).indices.iterator(); while(x.hasNext) { java.lang.System.out?.println(x.next()) } }");
System.out.println(generateToText());
Method foo = generateFunction();
foo.invoke(null);
@@ -1,5 +1,8 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author alex.tkachman
*/
@@ -13,4 +16,29 @@ public class FunctionGenTest extends CodegenTestCase {
blackBoxFile("functions/nothisnoclosure.jet");
System.out.println(generateToText());
}
public void testAnyToString () throws InvocationTargetException, IllegalAccessException {
loadText("fun foo(x: Any) = x.toString()");
System.out.println(generateToText());
Method foo = generateFunction();
assertEquals("something", foo.invoke(null, "something"));
assertEquals("null", foo.invoke(null, new Object[]{null}));
}
public void testAnyEqualsNullable () throws InvocationTargetException, IllegalAccessException {
loadText("fun foo(x: Any?) = x.equals(\"lala\")");
System.out.println(generateToText());
Method foo = generateFunction();
assertTrue((Boolean) foo.invoke(null, "lala"));
assertFalse((Boolean) foo.invoke(null, "mama"));
}
public void testAnyEquals () throws InvocationTargetException, IllegalAccessException {
loadText("fun foo(x: Any) = x.equals(\"lala\")");
System.out.println(generateToText());
Method foo = generateFunction();
assertTrue((Boolean) foo.invoke(null, "lala"));
assertFalse((Boolean) foo.invoke(null, "mama"));
}
}
@@ -0,0 +1,29 @@
package org.jetbrains.jet.codegen;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* @author alex.tkachman
*/
public class VarArgTest extends CodegenTestCase {
public void testStringArray () throws InvocationTargetException, IllegalAccessException {
/*
loadText("fun test(vararg ts: String) = ts");
System.out.println(generateToText());
final Method main = generateFunction();
Object[] args = {"mama", "papa"};
assertTrue(args == main.invoke(null, args));
*/
}
public void testIntArray () throws InvocationTargetException, IllegalAccessException {
/*
loadText("fun test(vararg ts: Int) = ts");
System.out.println(generateToText());
final Method main = generateFunction();
int[] args = {3, 4};
assertTrue(args == main.invoke(null, args));
*/
}
}