Merge remote branch 'origin/master'

This commit is contained in:
Andrey Breslav
2011-10-28 15:23:37 +04:00
110 changed files with 615 additions and 500 deletions
@@ -1,5 +1,6 @@
/* /*
* @author max * @author max
* @author alex.tkachman
*/ */
package org.jetbrains.jet.codegen; package org.jetbrains.jet.codegen;
@@ -16,9 +17,7 @@ import org.objectweb.asm.commons.Method;
import org.objectweb.asm.signature.SignatureWriter; import org.objectweb.asm.signature.SignatureWriter;
import java.util.Arrays; import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.objectweb.asm.Opcodes.*; import static org.objectweb.asm.Opcodes.*;
@@ -152,6 +151,9 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
final Method bridge = erasedInvokeSignature(funDescriptor); final Method bridge = erasedInvokeSignature(funDescriptor);
final Method delegate = invokeSignature(funDescriptor); final Method delegate = invokeSignature(funDescriptor);
if(bridge.getDescriptor().equals(delegate.getDescriptor()))
return;
final MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]); final MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "invoke", bridge.getDescriptor(), state.getTypeMapper().genericSignature(funDescriptor), new String[0]);
mv.visitCode(); mv.visitCode();
@@ -212,7 +214,8 @@ public class ClosureCodegen extends FunctionOrClosureCodegen {
ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state); ExpressionCodegen expressionCodegen = new ExpressionCodegen(mv, null, Type.VOID_TYPE, context, state);
iv.load(0, Type.getObjectType(funClass)); iv.load(0, Type.getObjectType(funClass));
expressionCodegen.generateTypeInfo(new ProjectionErasingJetType(returnType)); // expressionCodegen.generateTypeInfo(new ProjectionErasingJetType(returnType));
iv.aconst(null); // @todo
iv.invokespecial(funClass, "<init>", "(Ljet/typeinfo/TypeInfo;)V"); iv.invokespecial(funClass, "<init>", "(Ljet/typeinfo/TypeInfo;)V");
i = 1; i = 1;
@@ -313,10 +313,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
myContinueTargets.pop(); myContinueTargets.pop();
} }
private DeclarationDescriptor contextType() {
return context.getContextClass();
}
private OwnerKind contextKind() { private OwnerKind contextKind() {
return context.getContextKind(); return context.getContextKind();
} }
@@ -874,7 +870,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
String owner; String owner;
boolean isInterface; boolean isInterface;
boolean isInsideClass = containingDeclaration == contextType(); boolean isInsideClass = containingDeclaration == context.getContextClass();
if (isInsideClass || isStatic) { if (isInsideClass || isStatic) {
owner = typeMapper.getOwner(functionDescriptor, contextKind()); owner = typeMapper.getOwner(functionDescriptor, contextKind());
isInterface = false; isInterface = false;
@@ -904,7 +900,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl; boolean isStatic = containingDeclaration instanceof NamespaceDescriptorImpl;
propertyDescriptor = propertyDescriptor.getOriginal(); propertyDescriptor = propertyDescriptor.getOriginal();
boolean isInsideClass = !forceInterface && containingDeclaration == contextType(); boolean isInsideClass = !forceInterface && containingDeclaration == context.getContextClass();
Method getter; Method getter;
Method setter; Method setter;
if (forceField) { if (forceField) {
@@ -1024,10 +1020,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return funDescriptor; return funDescriptor;
} }
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression) {
invokeMethodWithArguments(callableMethod, expression, StackValue.none());
}
public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) { public void invokeMethodWithArguments(CallableMethod callableMethod, JetCallElement expression, StackValue receiver) {
final Type calleeType = callableMethod.getGenerateCalleeType(); final Type calleeType = callableMethod.getGenerateCalleeType();
if (calleeType != null && expression instanceof JetCallExpression) { if (calleeType != null && expression instanceof JetCallExpression) {
@@ -1053,7 +1045,11 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
else { else {
if (callableMethod.isNeedsReceiver()) { if (callableMethod.isNeedsReceiver()) {
receiver.put(JetTypeMapper.TYPE_OBJECT, v); if (receiver == StackValue.none()) {
v.load(0, JetTypeMapper.TYPE_OBJECT);
}
else
receiver.put(JetTypeMapper.TYPE_OBJECT, v);
} }
} }
@@ -1812,7 +1808,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION); CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
invokeMethodWithArguments(method, expression); invokeMethodWithArguments(method, expression, StackValue.none());
} }
} }
else { else {
@@ -1849,7 +1845,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.anew(type); v.anew(type);
v.dup(); v.dup();
final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructor); final CallableMethod callableMethod = typeMapper.mapToCallableMethod(constructor);
invokeMethodWithArguments(callableMethod, expression); invokeMethodWithArguments(callableMethod, expression, StackValue.none());
return type; return type;
} }
@@ -1867,20 +1863,22 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
throw new CompilationException("primitive array constructor requires one argument"); throw new CompilationException("primitive array constructor requires one argument");
} }
} }
gen(args.get(0).getArgumentExpression(), Type.INT_TYPE);
if(isArray) { if(isArray) {
JetType elementType = typeMapper.getGenericsElementType(arrayType); JetType elementType = typeMapper.getGenericsElementType(arrayType);
if(elementType != null) { if(elementType != null) {
generateTypeInfo(elementType); generateTypeInfo(elementType);
v.invokestatic("jet/typeinfo/TypeInfo", "newArray", "(ILjet/typeinfo/TypeInfo;)[Ljava/lang/Object;"); gen(args.get(0).getArgumentExpression(), Type.INT_TYPE);
v.invokevirtual("jet/typeinfo/TypeInfo", "newArray", "(I)[Ljava/lang/Object;");
} }
else { else {
gen(args.get(0).getArgumentExpression(), Type.INT_TYPE);
v.newarray(JetTypeMapper.boxType(typeMapper.mapType(arrayType.getArguments().get(0).getType()))); v.newarray(JetTypeMapper.boxType(typeMapper.mapType(arrayType.getArguments().get(0).getType())));
} }
} }
else { else {
Type type = typeMapper.mapType(arrayType, OwnerKind.IMPLEMENTATION); Type type = typeMapper.mapType(arrayType, OwnerKind.IMPLEMENTATION);
gen(args.get(0).getArgumentExpression(), Type.INT_TYPE);
v.newarray(type.getElementType()); v.newarray(type.getElementType());
} }
@@ -2311,12 +2309,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
return; return;
} }
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
if (contextType() instanceof ClassDescriptor) { if (context.getContextClass() instanceof ClassDescriptor) {
ClassDescriptor descriptor = (ClassDescriptor) contextType(); ClassDescriptor descriptor = (ClassDescriptor) context.getContextClass();
JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType(); JetType defaultType = ((ClassDescriptor)containingDeclaration).getDefaultType();
Type ownerType = typeMapper.mapType(defaultType); Type ownerType = typeMapper.mapType(defaultType);
ownerType = JetTypeMapper.boxType(ownerType); ownerType = JetTypeMapper.boxType(ownerType);
if (containingDeclaration == contextType()) { if (containingDeclaration == context.getContextClass()) {
if(!CodegenUtil.isInterface(descriptor)) { if(!CodegenUtil.isInterface(descriptor)) {
if (CodegenUtil.hasTypeInfoField(defaultType)) { if (CodegenUtil.hasTypeInfoField(defaultType)) {
v.load(0, JetTypeMapper.TYPE_OBJECT); v.load(0, JetTypeMapper.TYPE_OBJECT);
@@ -461,7 +461,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind); CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, kind);
codegen.invokeMethodWithArguments(method, constructorCall); codegen.invokeMethodWithArguments(method, constructorCall, StackValue.none());
} }
@Override @Override
@@ -513,7 +513,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier; final JetDelegatorToSuperCall superCall = (JetDelegatorToSuperCall) specifier;
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression()); ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) state.getBindingContext().get(BindingContext.REFERENCE_TARGET, superCall.getCalleeExpression().getConstructorReferenceExpression());
CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION); CallableMethod method = state.getTypeMapper().mapToCallableMethod(constructorDescriptor, OwnerKind.IMPLEMENTATION);
codegen.invokeMethodWithArguments(method, superCall); codegen.invokeMethodWithArguments(method, superCall, StackValue.none());
} }
else { else {
throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier); throw new UnsupportedOperationException("unsupported type of enum constant initializer: " + specifier);
@@ -75,6 +75,7 @@ public class IntrinsicMethods {
declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString()); declareOverload(myStdLib.getLibraryScope().getFunctions("toString"), 0, new ToString());
declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, new Equals()); declareOverload(myStdLib.getLibraryScope().getFunctions("equals"), 1, new Equals());
declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus());
// declareIntrinsicFunction("Any", "equals", 1, new Equals()); // declareIntrinsicFunction("Any", "equals", 1, new Equals());
// //
@@ -0,0 +1,28 @@
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.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 StringPlus implements IntrinsicMethod {
@Override
public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, PsiElement element, List<JetExpression> arguments, StackValue receiver) {
codegen.gen(arguments.get(0)).put(JetTypeMapper.JL_STRING_TYPE, v);
codegen.gen(arguments.get(1)).put(JetTypeMapper.TYPE_OBJECT, v);
v.invokestatic("jet/runtime/Intrinsics", "stringPlus", "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;");
return StackValue.onStack(JetTypeMapper.JL_STRING_TYPE);
}
}
@@ -1,6 +1,8 @@
package org.jetbrains.jet.cli; package org.jetbrains.jet.cli;
import com.google.common.collect.*; import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.intellij.core.JavaCoreEnvironment; import com.intellij.core.JavaCoreEnvironment;
import com.intellij.openapi.Disposable; import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
@@ -10,6 +12,7 @@ import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager; import com.intellij.psi.PsiManager;
import com.sampullara.cli.Args; import com.sampullara.cli.Args;
import com.sampullara.cli.Argument; import com.sampullara.cli.Argument;
import org.jetbrains.jet.JetCoreEnvironment;
import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GenerationState; import org.jetbrains.jet.codegen.GenerationState;
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory; import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
@@ -17,13 +20,11 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithTextRange;
import org.jetbrains.jet.lang.diagnostics.Severity; 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.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespace; import org.jetbrains.jet.lang.psi.JetNamespace;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports; import org.jetbrains.jet.lang.resolve.java.JavaDefaultImports;
import org.jetbrains.jet.plugin.JetFileType;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -61,17 +62,13 @@ public class KotlinCompiler {
public void dispose() { public void dispose() {
} }
}; };
JavaCoreEnvironment environment = new JavaCoreEnvironment(root); JetCoreEnvironment environment = new JetCoreEnvironment(root);
File rtJar = initJdk(); File rtJar = initJdk();
if (rtJar == null) return; if (rtJar == null) return;
environment.addToClasspath(rtJar); environment.addToClasspath(rtJar);
environment.registerFileType(JetFileType.INSTANCE, "kt");
environment.registerFileType(JetFileType.INSTANCE, "jet");
environment.registerParserDefinition(new JetParserDefinition());
VirtualFile vFile = environment.getLocalFileSystem().findFileByPath(arguments.src); VirtualFile vFile = environment.getLocalFileSystem().findFileByPath(arguments.src);
if (vFile == null) { if (vFile == null) {
System.out.print("File/directory not found: " + arguments.src); System.out.print("File/directory not found: " + arguments.src);
+2
View File
@@ -40,6 +40,8 @@ fun Any?.equals(other : Any?) : Boolean// = this === other
// Returns "null" for null // Returns "null" for null
fun Any?.toString() : String// = this === other fun Any?.toString() : String// = this === other
fun String?.plus(other: Any?) : String
trait Iterator<out T> { trait Iterator<out T> {
fun next() : T fun next() : T
val hasNext : Boolean val hasNext : Boolean
@@ -12,6 +12,8 @@ public class JetCoreEnvironment extends JavaCoreEnvironment {
public JetCoreEnvironment(Disposable parentDisposable) { public JetCoreEnvironment(Disposable parentDisposable) {
super(parentDisposable); super(parentDisposable);
registerFileType(JetFileType.INSTANCE, "kt"); registerFileType(JetFileType.INSTANCE, "kt");
registerFileType(JetFileType.INSTANCE, "kts");
registerFileType(JetFileType.INSTANCE, "ktm");
registerFileType(JetFileType.INSTANCE, "jet"); registerFileType(JetFileType.INSTANCE, "jet");
registerParserDefinition(new JetParserDefinition()); registerParserDefinition(new JetParserDefinition());
} }
@@ -0,0 +1,116 @@
package org.jetbrains.jet.lang.cfg;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.jetbrains.jet.lang.cfg.pseudocode.Instruction;
import org.jetbrains.jet.lang.cfg.pseudocode.LocalDeclarationInstruction;
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
import org.jetbrains.jet.lang.cfg.pseudocode.SubroutineEnterInstruction;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @author svtk
*/
public class JetControlFlowGraphTraverser {
public static <D> Map<Instruction, D> traverseInstructionGraphUntilFactsStabilization(
Pseudocode pseudocode,
InstructionsMergeStrategy<D> instructionsMergeStrategy,
D initialDataValue,
D initialDataValueForEnterInstruction,
boolean straightDirection) {
Map<Instruction, D> dataMap = Maps.newHashMap();
initializeDataMap(dataMap, pseudocode, initialDataValue);
dataMap.put(pseudocode.getEnterInstruction(), initialDataValueForEnterInstruction);
boolean[] changed = new boolean[1];
changed[0] = true;
while (changed[0]) {
changed[0] = false;
traverseSubGraph(pseudocode, instructionsMergeStrategy, Collections.<Instruction>emptyList(), straightDirection, dataMap, changed, false);
}
return dataMap;
}
private static <D> void initializeDataMap(
Map<Instruction, D> dataMap,
Pseudocode pseudocode,
D initialDataValue) {
List<Instruction> instructions = pseudocode.getInstructions();
for (Instruction instruction : instructions) {
dataMap.put(instruction, initialDataValue);
if (instruction instanceof LocalDeclarationInstruction) {
initializeDataMap(dataMap, ((LocalDeclarationInstruction) instruction).getBody(), initialDataValue);
}
}
}
private static <D> void traverseSubGraph(
Pseudocode pseudocode,
InstructionsMergeStrategy<D> instructionsMergeStrategy,
Collection<Instruction> previousSubGraphInstructions,
boolean straightDirection,
Map<Instruction, D> dataMap,
boolean[] changed,
boolean isLocal) {
List<Instruction> instructions = pseudocode.getInstructions();
SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
for (Instruction instruction : instructions) {
if (!isLocal && instruction instanceof SubroutineEnterInstruction) continue;
Collection<Instruction> allPreviousInstructions;
Collection<Instruction> previousInstructions = straightDirection
? instruction.getPreviousInstructions()
: instruction.getNextInstructions();
if (instruction == enterInstruction && !previousSubGraphInstructions.isEmpty()) {
allPreviousInstructions = Lists.newArrayList(previousInstructions);
allPreviousInstructions.addAll(previousSubGraphInstructions);
}
else {
allPreviousInstructions = previousInstructions;
}
if (instruction instanceof LocalDeclarationInstruction) {
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
traverseSubGraph(subroutinePseudocode, instructionsMergeStrategy, previousInstructions, straightDirection, dataMap, changed, true);
}
D previousDataValue = dataMap.get(instruction);
Collection<D> incomingEdgesData = Sets.newHashSet();
for (Instruction previousInstruction : allPreviousInstructions) {
incomingEdgesData.add(dataMap.get(previousInstruction));
}
D mergedData = instructionsMergeStrategy.execute(instruction, incomingEdgesData);
if (!mergedData.equals(previousDataValue)) {
changed[0] = true;
dataMap.put(instruction, mergedData);
}
}
}
public static void traverseAndAnalyzeInstructionGraph(
Pseudocode pseudocode,
InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) {
List<Instruction> instructions = pseudocode.getInstructions();
for (Instruction instruction : instructions) {
if (instruction instanceof LocalDeclarationInstruction) {
traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy);
}
instructionDataAnalyzeStrategy.execute(instruction);
}
}
interface InstructionsMergeStrategy<D> {
D execute(Instruction instruction, Collection<D> incomingEdgesData);
}
interface InstructionDataAnalyzeStrategy {
void execute(Instruction instruction);
}
}
@@ -5,10 +5,12 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions; import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
@@ -590,6 +592,17 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitCallExpression(JetCallExpression expression) { public void visitCallExpression(JetCallExpression expression) {
//inline functions after M1
// ResolvedCall<? extends CallableDescriptor> resolvedCall = trace.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
// assert resolvedCall != null;
// CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
// PsiElement element = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, resultingDescriptor);
// if (element instanceof JetNamedFunction) {
// JetNamedFunction namedFunction = (JetNamedFunction) element;
// if (namedFunction.hasModifier(JetTokens.INLINE_KEYWORD)) {
// }
// }
for (JetTypeProjection typeArgument : expression.getTypeArguments()) { for (JetTypeProjection typeArgument : expression.getTypeArguments()) {
value(typeArgument, false); value(typeArgument, false);
} }
@@ -726,6 +739,9 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitObjectDeclaration(JetObjectDeclaration declaration) { public void visitObjectDeclaration(JetObjectDeclaration declaration) {
// for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) {
// value(delegationSpecifier, inCondition);
// }
Queue<Label> declarationLabels = new LinkedList<Label>(); Queue<Label> declarationLabels = new LinkedList<Label>();
List<JetDeclaration> declarations = declaration.getDeclarations(); List<JetDeclaration> declarations = declaration.getDeclarations();
for (JetDeclaration localDeclaration : declarations) { for (JetDeclaration localDeclaration : declarations) {
@@ -734,27 +750,19 @@ public class JetControlFlowProcessor {
builder.nondeterministicJump(Lists.newArrayList(declarationLabels)); builder.nondeterministicJump(Lists.newArrayList(declarationLabels));
for (JetDeclaration localDeclaration : declarations) { for (JetDeclaration localDeclaration : declarations) {
if (localDeclaration instanceof JetNamedDeclaration) { if (localDeclaration instanceof JetNamedDeclaration) {
if (localDeclaration instanceof JetFunction) { if (localDeclaration instanceof JetDeclarationWithBody) {
//TODO JetExpression bodyExpression = ((JetDeclarationWithBody) localDeclaration).getBodyExpression();
generate(localDeclaration, ((JetFunction) localDeclaration).getBodyExpression()); generate(localDeclaration, bodyExpression != null ? bodyExpression : localDeclaration);
} }
else { else {
generate(localDeclaration, localDeclaration); generate(localDeclaration, localDeclaration);
} }
} }
else { else {
//todo
generate(declaration, localDeclaration); generate(declaration, localDeclaration);
} }
builder.bindLabel(declarationLabels.remove()); builder.bindLabel(declarationLabels.remove());
} }
// for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) {
// value(delegationSpecifier, inCondition);
// }
// for (JetDeclaration jetDeclaration : declaration.getDeclarations()) {
// //FOR_LOCAL_CLASSES.
// value(jetDeclaration, false);
// }
} }
@Override @Override
@@ -8,10 +8,13 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.LocalVariableDescriptor; import org.jetbrains.jet.lang.descriptors.LocalVariableDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.types.JetStandardClasses;
import java.util.*; import java.util.*;
@@ -256,103 +259,25 @@ public class JetFlowInformationProvider {
// } // }
// } // }
private <D> Map<Instruction, D> traverseInstructionGraphUntilFactsStabilization( public void markUninitializedVariables(@NotNull JetElement subroutine, List<? extends VariableDescriptor> initializedVariables) {
Pseudocode pseudocode,
InstructionsMergeHandler<D> instructionsMergeHandler,
D initialDataValue,
D initialDataValueForEnterInstruction,
boolean straightDirection) {
Map<Instruction, D> dataMap = Maps.newHashMap();
initializeDataMap(dataMap, pseudocode, initialDataValue);
dataMap.put(pseudocode.getEnterInstruction(), initialDataValueForEnterInstruction);
boolean[] changed = new boolean[1];
changed[0] = true;
while (changed[0]) {
changed[0] = false;
traverseSubGraph(pseudocode, instructionsMergeHandler, Collections.<Instruction>emptyList(), straightDirection, dataMap, changed, false);
}
return dataMap;
}
private <D> void initializeDataMap(
Map<Instruction, D> dataMap,
Pseudocode pseudocode,
D initialDataValue) {
List<Instruction> instructions = pseudocode.getInstructions();
for (Instruction instruction : instructions) {
dataMap.put(instruction, initialDataValue);
if (instruction instanceof LocalDeclarationInstruction) {
initializeDataMap(dataMap, ((LocalDeclarationInstruction) instruction).getBody(), initialDataValue);
}
}
}
private <D> void traverseSubGraph(
Pseudocode pseudocode,
InstructionsMergeHandler<D> instructionsMergeHandler,
Collection<Instruction> previousSubGraphInstructions,
boolean straightDirection,
Map<Instruction, D> dataMap,
boolean[] changed,
boolean isLocal) {
List<Instruction> instructions = pseudocode.getInstructions();
SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
for (Instruction instruction : instructions) {
if (!isLocal && instruction instanceof SubroutineEnterInstruction) continue;
Collection<Instruction> allPreviousInstructions;
Collection<Instruction> previousInstructions = straightDirection
? instruction.getPreviousInstructions()
: instruction.getNextInstructions();
if (instruction == enterInstruction && !previousSubGraphInstructions.isEmpty()) {
allPreviousInstructions = Lists.newArrayList(previousInstructions);
allPreviousInstructions.addAll(previousSubGraphInstructions);
}
else {
allPreviousInstructions = previousInstructions;
}
if (instruction instanceof LocalDeclarationInstruction) {
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
traverseSubGraph(subroutinePseudocode, instructionsMergeHandler, previousInstructions, straightDirection, dataMap, changed, true);
}
D previousDataValue = dataMap.get(instruction);
Collection<D> incomingEdgesData = Sets.newHashSet();
for (Instruction previousInstruction : allPreviousInstructions) {
incomingEdgesData.add(dataMap.get(previousInstruction));
}
D mergedData = instructionsMergeHandler.merge(instruction, incomingEdgesData);
if (!mergedData.equals(previousDataValue)) {
changed[0] = true;
dataMap.put(instruction, mergedData);
}
}
}
public void markUninitializedVariables(@NotNull JetElement subroutine) {
Pseudocode pseudocode = pseudocodeMap.get(subroutine); Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null; assert pseudocode != null;
Collection<Instruction> instructions = pseudocode.getInstructions(); JetControlFlowGraphTraverser.InstructionsMergeStrategy<Map<VariableDescriptor, InitializationPoints>> instructionsMergeStrategy = new JetControlFlowGraphTraverser.InstructionsMergeStrategy<Map<VariableDescriptor, InitializationPoints>>() {
InstructionsMergeHandler<Map<LocalVariableDescriptor, InitializationPoints>> instructionsMergeHandler = new InstructionsMergeHandler<Map<LocalVariableDescriptor, InitializationPoints>>() {
@Override @Override
public Map<LocalVariableDescriptor, InitializationPoints> merge( public Map<VariableDescriptor, InitializationPoints> execute(
Instruction instruction, Instruction instruction,
Collection<Map<LocalVariableDescriptor, InitializationPoints>> incomingEdgesData) { Collection<Map<VariableDescriptor, InitializationPoints>> incomingEdgesData) {
Set<LocalVariableDescriptor> variablesInScope = Sets.newHashSet(); Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
for (Map<LocalVariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) { for (Map<VariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) {
variablesInScope.addAll(edgePointsMap.keySet()); variablesInScope.addAll(edgePointsMap.keySet());
} }
Map<LocalVariableDescriptor, InitializationPoints> pointsMap = Maps.newHashMap(); Map<VariableDescriptor, InitializationPoints> pointsMap = Maps.newHashMap();
for (LocalVariableDescriptor variable : variablesInScope) { for (VariableDescriptor variable : variablesInScope) {
Set<InitializationPoints> edgesDataForVariable = Sets.newHashSet(); Set<InitializationPoints> edgesDataForVariable = Sets.newHashSet();
for (Map<LocalVariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) { for (Map<VariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) {
InitializationPoints points = edgePointsMap.get(variable); InitializationPoints points = edgePointsMap.get(variable);
if (points != null) { if (points != null) {
edgesDataForVariable.add(points); edgesDataForVariable.add(points);
@@ -362,81 +287,95 @@ public class JetFlowInformationProvider {
} }
if (instruction instanceof WriteValueInstruction) { if (instruction instanceof WriteValueInstruction) {
LocalVariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction); VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
// DeclarationDescriptor descriptor = null;
// JetElement lValue = ((WriteValueInstruction) instruction).getlValue();
// if (lValue instanceof JetProperty || lValue instanceof JetParameter) {
// descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, lValue);
// }
// else if (lValue instanceof JetSimpleNameExpression) {
// descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) lValue);
// }
// if (descriptor instanceof LocalVariableDescriptor) {
// LocalVariableDescriptor variableDescriptor = (LocalVariableDescriptor) descriptor;
InitializationPoints initializationAtThisPoint = new InitializationPoints(((WriteValueInstruction) instruction).getElement()); InitializationPoints initializationAtThisPoint = new InitializationPoints(((WriteValueInstruction) instruction).getElement());
pointsMap.put(variableDescriptor, initializationAtThisPoint); pointsMap.put(variableDescriptor, initializationAtThisPoint);
// }
} }
return pointsMap; return pointsMap;
} }
}; };
Set<LocalVariableDescriptor> localVariables = collectAllLocalVariables(pseudocode); Set<VariableDescriptor> localVariables = collectAllLocalVariables(pseudocode);
Map<LocalVariableDescriptor, InitializationPoints> initialMapForStartInstruction = Maps.newHashMap(); Map<VariableDescriptor, InitializationPoints> initialMapForStartInstruction = Maps.newHashMap();
InitializationPoints initialPoints = new InitializationPoints(); InitializationPoints initialPointsForLocalVariable = new InitializationPoints(true);
for (LocalVariableDescriptor variable : localVariables) { for (VariableDescriptor variable : localVariables) {
initialMapForStartInstruction.put(variable, initialPoints); initialMapForStartInstruction.put(variable, initialPointsForLocalVariable);
} }
Map<Instruction, Map<LocalVariableDescriptor, InitializationPoints>> dataMap = InitializationPoints initialPointsForParameter = new InitializationPoints(false);
traverseInstructionGraphUntilFactsStabilization(pseudocode, instructionsMergeHandler, Collections.<LocalVariableDescriptor, InitializationPoints>emptyMap(), initialMapForStartInstruction, true); for (VariableDescriptor initializedVariable : initializedVariables) {
initialMapForStartInstruction.put(initializedVariable, initialPointsForParameter);
}
final Map<Instruction, Map<VariableDescriptor, InitializationPoints>> dataMap =
JetControlFlowGraphTraverser.traverseInstructionGraphUntilFactsStabilization(pseudocode, instructionsMergeStrategy, Collections.<VariableDescriptor, InitializationPoints>emptyMap(), initialMapForStartInstruction, true);
InstructionDataAnalyzer<Map<LocalVariableDescriptor, InitializationPoints>> instructionDataAnalyzer = new InstructionDataAnalyzer<Map<LocalVariableDescriptor, InitializationPoints>>() { JetControlFlowGraphTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() {
@Override @Override
public void analyze(Instruction instruction, Map<Instruction, Map<LocalVariableDescriptor, InitializationPoints>> dataMap) { public void execute(Instruction instruction) {
Map<LocalVariableDescriptor, InitializationPoints> variablesData = dataMap.get(instruction); Map<VariableDescriptor, InitializationPoints> variablesData = dataMap.get(instruction);
if (instruction instanceof ReadValueInstruction) { if (instruction instanceof ReadValueInstruction) {
LocalVariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction); VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
JetElement element = ((ReadValueInstruction) instruction).getElement(); JetElement element = ((ReadValueInstruction) instruction).getElement();
if (element instanceof JetSimpleNameExpression && variableDescriptor != null) { if (element instanceof JetSimpleNameExpression && variableDescriptor instanceof LocalVariableDescriptor) {
// DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
// if (descriptor instanceof LocalVariableDescriptor) {
InitializationPoints initializationPoints = variablesData.get(variableDescriptor); InitializationPoints initializationPoints = variablesData.get(variableDescriptor);
assert initializationPoints != null; assert initializationPoints != null;
if (initializationPoints.canBeUninitialized) { if (initializationPoints.canBeUninitialized) {
trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor)); trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor));
} }
// }
} }
} }
else if (instruction instanceof WriteValueInstruction) { else if (instruction instanceof WriteValueInstruction) {
JetElement element = ((WriteValueInstruction) instruction).getlValue(); JetElement element = ((WriteValueInstruction) instruction).getlValue();
LocalVariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction); VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
if (element instanceof JetSimpleNameExpression && variableDescriptor != null) { if (element instanceof JetSimpleNameExpression && variableDescriptor != null) {
// DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
// if (descriptor instanceof LocalVariableDescriptor) {
InitializationPoints initializationPoints = variablesData.get(variableDescriptor); InitializationPoints initializationPoints = variablesData.get(variableDescriptor);
assert initializationPoints != null; assert initializationPoints != null;
if (initializationPoints.hasPossibleInitializers() && !variableDescriptor.isVar()) { if (initializationPoints.hasPossibleInitializers() && !variableDescriptor.isVar()) {
trace.report(Errors.VAL_REASSIGNMENT.on((JetSimpleNameExpression) element, variableDescriptor)); trace.report(Errors.VAL_REASSIGNMENT.on((JetSimpleNameExpression) element, variableDescriptor));
} }
// }
} }
} }
} }
}; });
traverseAndAnalyzeInstructionGraph(instructions, dataMap, instructionDataAnalyzer); }
public void markNotOnlyInvokedFunctionVariables(@NotNull JetElement subroutine, List<? extends VariableDescriptor> variables) {
final List<VariableDescriptor> functionVariables = Lists.newArrayList();
for (VariableDescriptor variable : variables) {
if (JetStandardClasses.isFunctionType(variable.getReturnType())) {
functionVariables.add(variable);
}
}
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
assert pseudocode != null;
JetControlFlowGraphTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() {
@Override
public void execute(Instruction instruction) {
if (instruction instanceof ReadValueInstruction) {
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
if (variableDescriptor != null && functionVariables.contains(variableDescriptor)) {
//check that we only invoke this variable
JetElement element = ((ReadValueInstruction) instruction).getElement();
if (element instanceof JetSimpleNameExpression && !(element.getParent() instanceof JetCallExpression)) {
trace.report(Errors.FUNCTION_PARAMETERS_OF_INLINE_FUNCTION.on((JetSimpleNameExpression)element, variableDescriptor));
}
}
}
}
});
} }
@Nullable @Nullable
private LocalVariableDescriptor extractVariableDescriptorIfAny(Instruction instruction) { private VariableDescriptor extractVariableDescriptorIfAny(Instruction instruction) {
LocalVariableDescriptor variableDescriptor = null; VariableDescriptor variableDescriptor = null;
if (instruction instanceof ReadValueInstruction) { if (instruction instanceof ReadValueInstruction) {
JetElement element = ((ReadValueInstruction) instruction).getElement(); JetElement element = ((ReadValueInstruction) instruction).getElement();
if (element instanceof JetSimpleNameExpression) { if (element instanceof JetSimpleNameExpression) {
DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element); DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
if (descriptor instanceof LocalVariableDescriptor) { if (descriptor instanceof VariableDescriptor) {
variableDescriptor = (LocalVariableDescriptor) descriptor; variableDescriptor = (VariableDescriptor) descriptor;
} }
} }
} }
@@ -449,51 +388,34 @@ public class JetFlowInformationProvider {
else if (lValue instanceof JetSimpleNameExpression) { else if (lValue instanceof JetSimpleNameExpression) {
descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) lValue); descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) lValue);
} }
if (descriptor instanceof LocalVariableDescriptor) { if (descriptor instanceof VariableDescriptor) {
variableDescriptor = (LocalVariableDescriptor) descriptor; variableDescriptor = (VariableDescriptor) descriptor;
} }
} }
return variableDescriptor; return variableDescriptor;
} }
private Set<LocalVariableDescriptor> collectAllLocalVariables(Pseudocode pseudocode) { private Set<VariableDescriptor> collectAllLocalVariables(Pseudocode pseudocode) {
final Set<LocalVariableDescriptor> localVariables = Sets.newHashSet(); final Set<VariableDescriptor> localVariables = Sets.newHashSet();
InstructionDataAnalyzer<Void> analyzer = new InstructionDataAnalyzer<Void>() { JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy analyzeStrategy = new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() {
@Override @Override
public void analyze(Instruction instruction, Map<Instruction, Void> dataMap) { public void execute(Instruction instruction) {
LocalVariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction); VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
if (variableDescriptor != null) { if (variableDescriptor != null) {
localVariables.add(variableDescriptor); localVariables.add(variableDescriptor);
} }
} }
}; };
traverseAndAnalyzeInstructionGraph(pseudocode.getInstructions(), Collections.<Instruction, Void>emptyMap(), analyzer); JetControlFlowGraphTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, analyzeStrategy);
return localVariables; return localVariables;
} }
private <D> void traverseAndAnalyzeInstructionGraph(Collection<Instruction> instructions, Map<Instruction, D> dataMap, InstructionDataAnalyzer<D> instructionDataAnalyzer) {
for (Instruction instruction : instructions) {
if (instruction instanceof LocalDeclarationInstruction) {
traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody().getInstructions(), dataMap, instructionDataAnalyzer);
}
instructionDataAnalyzer.analyze(instruction, dataMap);
}
}
interface InstructionsMergeHandler<D> {
D merge(Instruction instruction, Collection<D> incomingEdgesData);
}
interface InstructionDataAnalyzer<D> {
void analyze(Instruction instruction, Map<Instruction, D> dataMap);
}
private static class InitializationPoints { private static class InitializationPoints {
private Set<JetElement> possiblePoints = Sets.newHashSet(); private Set<JetElement> possiblePoints = Sets.newHashSet();
private boolean canBeUninitialized; private boolean canBeUninitialized;
public InitializationPoints() { public InitializationPoints(boolean canBeUninitialized) {
canBeUninitialized = true; this.canBeUninitialized = canBeUninitialized;
} }
public InitializationPoints(JetElement element) { public InitializationPoints(JetElement element) {
@@ -145,6 +145,8 @@ public interface Errors {
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME); PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME);
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> VAL_REASSIGNMENT = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME); PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> VAL_REASSIGNMENT = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME);
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> FUNCTION_PARAMETERS_OF_INLINE_FUNCTION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Funciton parameters of inline funciton can only be invoked", NAME);
SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code"); SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code");
SimpleDiagnosticFactory MANY_CLASS_OBJECTS = SimpleDiagnosticFactory.create(ERROR, "Only one class object is allowed per class"); SimpleDiagnosticFactory MANY_CLASS_OBJECTS = SimpleDiagnosticFactory.create(ERROR, "Only one class object is allowed per class");
@@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetStandardClasses;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices; import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -113,7 +114,12 @@ public class ControlFlowAnalyzer {
}); });
} }
if (!declaredLocally) { if (!declaredLocally) {
flowInformationProvider.markUninitializedVariables(function.asElement()); flowInformationProvider.markUninitializedVariables(function.asElement(), functionDescriptor.getValueParameters());
if (((JetDeclaration) function).hasModifier(JetTokens.INLINE_KEYWORD)) {
//inline functions after M1
// flowInformationProvider.markNotOnlyInvokedFunctionVariables(function.asElement(), functionDescriptor.getValueParameters());
}
} }
} }
@@ -48,6 +48,13 @@ fun t2() {
fun doSmth(s: String) {} fun doSmth(s: String) {}
fun doSmth(i: Int) {} fun doSmth(i: Int) {}
class A() {}
fun t4(a: A, val b: A, var c: A) {
<!VAL_REASSIGNMENT!>a<!> = A()
<!VAL_REASSIGNMENT!>b<!> = A()
c = A()
}
} }
namespace reassigned_vals { namespace reassigned_vals {
@@ -52,7 +52,7 @@ abstract class Sum() : Iteratee<Int, Int> {
} }
abstract class Collection<E> : Iterable<E> { abstract class Collection<E> : Iterable<E> {
fun iterate<O>(iteratee : Iteratee<E, O>) : O { fun iterate<O>(var iteratee : Iteratee<E, O>) : O {
for (x in this) { for (x in this) {
val it = iteratee.process(x) val it = iteratee.process(x)
if (it.isDone) return it.result if (it.isDone) return it.result
@@ -1,4 +1,4 @@
class Foo(var bar : Int, barr : Int, val barrr : Int) { class Foo(var bar : Int, var barr : Int, var barrr : Int) {
{ {
bar = 1 bar = 1
barr = 1 barr = 1
@@ -7,7 +7,7 @@
this : Foo this : Foo
} }
this(val bar : Int) : this(1, 1, 1) { this(var bar : Int) : this(1, 1, 1) {
bar = 1 bar = 1
this.bar this.bar
1 : Int 1 : Int
@@ -1,4 +1,4 @@
fun loop(times : Int) { fun loop(var times : Int) {
while(times > 0) { while(times > 0) {
val u : fun(value : Int) : Unit = { val u : fun(value : Int) : Unit = {
System.out?.println(it) System.out?.println(it)
@@ -1,5 +1,5 @@
class C(x: Int, val y : Int) { class C(x: Int, val y : Int) {
fun initChild(x: Int) : java.lang.Object { fun initChild(var x: Int) : java.lang.Object {
return object : java.lang.Object() { return object : java.lang.Object() {
override fun toString(): String? { override fun toString(): String? {
x = x + y x = x + y
@@ -0,0 +1,12 @@
fun Any.with(operation : fun Any.() : Any) = operation().toString()
val f = { (a : Int) :Unit => }
fun box () : String {
return if(20.with {
this
} == "20")
"OK"
else
"fail"
}
@@ -1,16 +0,0 @@
package org.jetbrains.jet;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor;
/**
* @author yole
*/
public class JetLightProjectDescriptor extends DefaultLightProjectDescriptor {
public static JetLightProjectDescriptor INSTANCE = new JetLightProjectDescriptor();
@Override
public Sdk getSdk() {
return JetTestCaseBase.jdkFromIdeaHome();
}
}
@@ -14,6 +14,7 @@ import com.intellij.testFramework.LightVirtualFile;
import com.intellij.testFramework.TestDataFile; import com.intellij.testFramework.TestDataFile;
import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.UsefulTestCase;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.plugin.JetLanguage; import org.jetbrains.jet.plugin.JetLanguage;
import java.io.File; import java.io.File;
@@ -25,7 +26,7 @@ import java.io.IOException;
public abstract class JetLiteFixture extends UsefulTestCase { public abstract class JetLiteFixture extends UsefulTestCase {
@NonNls @NonNls
protected final String myFullDataPath; protected final String myFullDataPath;
protected PsiFile myFile; protected JetFile myFile;
private JetCoreEnvironment myEnvironment; private JetCoreEnvironment myEnvironment;
public JetLiteFixture(@NonNls String dataPath) { public JetLiteFixture(@NonNls String dataPath) {
@@ -37,7 +38,7 @@ public abstract class JetLiteFixture extends UsefulTestCase {
} }
protected String getTestDataPath() { protected String getTestDataPath() {
return JetTestCaseBase.getTestDataPathBase(); return JetTestCaseBuilder.getTestDataPathBase();
} }
public Project getProject() { public Project getProject() {
@@ -48,9 +49,9 @@ public abstract class JetLiteFixture extends UsefulTestCase {
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
myEnvironment = new JetCoreEnvironment(getTestRootDisposable()); myEnvironment = new JetCoreEnvironment(getTestRootDisposable());
final File rtJar = new File(JetTestCaseBase.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar"); final File rtJar = new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/rt.jar");
myEnvironment.addToClasspath(rtJar); myEnvironment.addToClasspath(rtJar);
myEnvironment.addToClasspath(new File(JetTestCaseBase.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar")); myEnvironment.addToClasspath(new File(JetTestCaseBuilder.getHomeDirectory(), "compiler/testData/mockJDK-1.7/jre/lib/annotations.jar"));
} }
@Override @Override
@@ -71,8 +72,16 @@ public abstract class JetLiteFixture extends UsefulTestCase {
return text; return text;
} }
protected PsiFile createPsiFile(String name, String text) { protected JetFile createPsiFile(String name, String text) {
return createFile(name + ".jet", text); return (JetFile) createFile(name + ".jet", text);
}
protected JetFile loadPsiFile(String name) {
try {
return createPsiFile(name, loadFile(name));
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
protected PsiFile createFile(@NonNls String name, String text) { protected PsiFile createFile(@NonNls String name, String text) {
@@ -1,9 +1,6 @@
package org.jetbrains.jet; package org.jetbrains.jet;
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -18,72 +15,20 @@ import java.util.List;
/** /**
* @author abreslav * @author abreslav
*/ */
public abstract class JetTestCaseBase extends LightDaemonAnalyzerTestCase { public abstract class JetTestCaseBuilder {
private static FilenameFilter emptyFilter = new FilenameFilter() {
private static FilenameFilter emptyFilter; @Override
private boolean checkInfos = false; public boolean accept(File file, String name) {
private String dataPath; return true;
protected final String name; }
};
public JetTestCaseBase(String dataPath, String name) {
this.dataPath = dataPath;
this.name = name;
}
public final JetTestCaseBase setCheckInfos(boolean checkInfos) {
this.checkInfos = checkInfos;
return this;
}
public static Sdk jdkFromIdeaHome() {
return new JavaSdkImpl().createJdk("JDK", "compiler/testData/mockJDK-1.7/jre", true);
}
@Override
protected String getTestDataPath() {
return getTestDataPathBase();
}
public static String getTestDataPathBase() { public static String getTestDataPathBase() {
return getHomeDirectory() + "/compiler/testData"; return getHomeDirectory() + "/compiler/testData";
} }
public static String getHomeDirectory() { public static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(JetTestCaseBase.class, "/org/jetbrains/jet/JetTestCaseBase.class")).getParentFile().getParentFile().getParent(); return new File(PathManager.getResourceRoot(JetTestCaseBuilder.class, "/org/jetbrains/jet/JetTestCaseBuilder.class")).getParentFile().getParentFile().getParent();
}
@Override
protected Sdk getProjectJDK() {
return jdkFromIdeaHome();
}
@Override
public String getName() {
return "test" + name;
}
@Override
protected void runTest() throws Throwable {
doTest(getTestFilePath(), true, checkInfos);
}
@NotNull
protected String getTestFilePath() {
return dataPath + File.separator + name + ".jet";
}
protected String getDataPath() {
return dataPath;
}
protected void setUp() throws Exception {
super.setUp();
emptyFilter = new FilenameFilter() {
@Override
public boolean accept(File file, String name) {
return true;
}
};
} }
public interface NamedTestFactory { public interface NamedTestFactory {
@@ -8,7 +8,8 @@ import com.intellij.openapi.util.text.StringUtil;
import junit.framework.Test; import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.lang.cfg.LoopInfo; import org.jetbrains.jet.lang.cfg.LoopInfo;
import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
@@ -20,19 +21,25 @@ import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.util.*; import java.util.*;
public class JetControlFlowTest extends JetTestCaseBase { public class JetControlFlowTest extends JetLiteFixture {
static { static {
System.setProperty("idea.platform.prefix", "Idea"); System.setProperty("idea.platform.prefix", "Idea");
} }
private String myName;
public JetControlFlowTest(String dataPath, String name) { public JetControlFlowTest(String dataPath, String name) {
super(dataPath, name); super(dataPath);
myName = name;
} }
protected String getTestFilePath() {
return myFullDataPath + "/" + myName;
}
@Override @Override
protected void runTest() throws Throwable { protected void runTest() throws Throwable {
configureByFile(getTestFilePath()); JetFile file = loadPsiFile(myName + ".jet");
JetFile file = (JetFile) getFile();
final Map<JetElement, Pseudocode> data = new LinkedHashMap<JetElement, Pseudocode>(); final Map<JetElement, Pseudocode> data = new LinkedHashMap<JetElement, Pseudocode>();
final JetPseudocodeTrace pseudocodeTrace = new JetPseudocodeTrace() { final JetPseudocodeTrace pseudocodeTrace = new JetPseudocodeTrace() {
@@ -68,14 +75,14 @@ public class JetControlFlowTest extends JetTestCaseBase {
}); });
try { try {
processCFData(name, data); processCFData(myName, data);
} }
catch (IOException e) { catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
finally { finally {
if ("true".equals(System.getProperty("jet.control.flow.test.dump.graphs"))) { if ("true".equals(System.getProperty("jet.control.flow.test.dump.graphs"))) {
dumpDot(name, data.values()); dumpDot(myName, data.values());
} }
} }
} }
@@ -120,7 +127,7 @@ public class JetControlFlowTest extends JetTestCaseBase {
} }
} }
String expectedInstructionsFileName = getTestDataPath() + "/" + getTestFilePath().replace(".jet", ".instructions"); String expectedInstructionsFileName = getTestFilePath() + ".instructions";
File expectedInstructionsFile = new File(expectedInstructionsFileName); File expectedInstructionsFile = new File(expectedInstructionsFileName);
if (!expectedInstructionsFile.exists()) { if (!expectedInstructionsFile.exists()) {
FileUtil.writeToFile(expectedInstructionsFile, instructionDump.toString()); FileUtil.writeToFile(expectedInstructionsFile, instructionDump.toString());
@@ -270,7 +277,6 @@ public class JetControlFlowTest extends JetTestCaseBase {
@Override @Override
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) { public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
//todo print edges //todo print edges
visitInstruction(instruction);
printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null); printEdge(out, nodeToName.get(instruction), nodeToName.get(instruction.getNext()), null);
} }
@@ -352,7 +358,7 @@ public class JetControlFlowTest extends JetTestCaseBase {
} }
private void dumpDot(String name, Collection<Pseudocode> pseudocodes) throws FileNotFoundException { private void dumpDot(String name, Collection<Pseudocode> pseudocodes) throws FileNotFoundException {
String graphFileName = getTestDataPath() + "/" + getTestFilePath().replace(".jet", ".dot"); String graphFileName = getTestDataPath() + "/" + getTestFilePath() + ".dot";
File target = new File(graphFileName); File target = new File(graphFileName);
PrintStream out = new PrintStream(target); PrintStream out = new PrintStream(target);
@@ -387,7 +393,7 @@ public class JetControlFlowTest extends JetTestCaseBase {
public static TestSuite suite() { public static TestSuite suite() {
TestSuite suite = new TestSuite(); TestSuite suite = new TestSuite();
suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/cfg/", true, new JetTestCaseBase.NamedTestFactory() { suite.addTest(JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/cfg/", true, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull @NotNull
@Override @Override
public Test createTest(@NotNull String dataPath, @NotNull String name) { public Test createTest(@NotNull String dataPath, @NotNull String name) {
@@ -2,39 +2,38 @@ package org.jetbrains.jet.checkers;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
import junit.framework.Test; import junit.framework.Test;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacade;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List; import java.util.List;
import java.util.regex.Pattern;
/** /**
* @author abreslav * @author abreslav
*/ */
public class FullJetPsiCheckerTest extends JetTestCaseBase { public class FullJetPsiCheckerTest extends JetLiteFixture {
private final String myDataPath;
private String myName;
public FullJetPsiCheckerTest(@NonNls String dataPath, String name) { public FullJetPsiCheckerTest(@NonNls String dataPath, String name) {
super(dataPath, name); myDataPath = dataPath;
myName = name;
} }
@Override
public String getName() {
return "test" + myName;
}
@Override @Override
public void runTest() throws Exception { public void runTest() throws Exception {
String fileName = name + ".jet"; String fileName = myName + ".jet";
String fullPath = getTestDataPath() + getTestFilePath(); String fullPath = myDataPath + "/" + fileName;
String expectedText = loadFile(fullPath); String expectedText = loadFile(fullPath);
@@ -42,9 +41,8 @@ public class FullJetPsiCheckerTest extends JetTestCaseBase {
List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList(); List<CheckerTestUtil.DiagnosedRange> diagnosedRanges = Lists.newArrayList();
String clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges); String clearText = CheckerTestUtil.parseDiagnosedRanges(expectedText, diagnosedRanges);
configureFromFileText(fileName, clearText); myFile = createPsiFile(myName, clearText);
JetFile jetFile = (JetFile) myFile; BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(myFile);
BindingContext bindingContext = AnalyzerFacade.analyzeFileWithCache(jetFile);
CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() { CheckerTestUtil.diagnosticsDiff(diagnosedRanges, bindingContext.getDiagnostics(), new CheckerTestUtil.DiagnosticDiffCallbacks() {
@Override @Override
@@ -60,7 +58,7 @@ public class FullJetPsiCheckerTest extends JetTestCaseBase {
} }
}); });
String actualText = CheckerTestUtil.addDiagnosticMarkersToText(jetFile, bindingContext).toString(); String actualText = CheckerTestUtil.addDiagnosticMarkersToText(myFile, bindingContext).toString();
assertEquals(expectedText, actualText); assertEquals(expectedText, actualText);
@@ -69,12 +67,7 @@ public class FullJetPsiCheckerTest extends JetTestCaseBase {
// convert(new File(myFullDataPath + "/../../checker/"), new File(myFullDataPath)); // convert(new File(myFullDataPath + "/../../checker/"), new File(myFullDataPath));
} }
private String loadFile(String fullPath) throws IOException { /*
final File ioFile = new File(fullPath);
String fileText = FileUtil.loadFile(ioFile, CharsetToolkit.UTF8);
return StringUtil.convertLineSeparators(fileText);
}
private void convert(File src, File dest) throws IOException { private void convert(File src, File dest) throws IOException {
File[] files = src.listFiles(); File[] files = src.listFiles();
for (File file : files) { for (File file : files) {
@@ -105,9 +98,10 @@ public class FullJetPsiCheckerTest extends JetTestCaseBase {
} }
} }
} }
*/
public static Test suite() { public static Test suite() {
return JetTestCaseBase.suiteForDirectory(JetTestCaseBase.getTestDataPathBase(), "/checkerWithErrorTypes/full/", true, new JetTestCaseBase.NamedTestFactory() { return JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/checkerWithErrorTypes/full/", true, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull @NotNull
@Override @Override
public Test createTest(@NotNull String dataPath, @NotNull String name) { public Test createTest(@NotNull String dataPath, @NotNull String name) {
@@ -1,42 +0,0 @@
package org.jetbrains.jet.checkers;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase;
/**
* @author abreslav
*/
public class JetPsiCheckerTest extends JetTestCaseBase {
public JetPsiCheckerTest(String dataPath, String name) {
super(dataPath, name);
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/checker/", false, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name);
}
}));
suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/checker/regression/", false, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name);
}
}));
suite.addTest(JetTestCaseBase.suiteForDirectory(getTestDataPathBase(), "/checker/infos/", false, new JetTestCaseBase.NamedTestFactory() {
@NotNull
@Override
public Test createTest(@NotNull String dataPath, @NotNull String name) {
return new JetPsiCheckerTest(dataPath, name).setCheckInfos(true);
}
}));
return suite;
}
}
@@ -6,7 +6,7 @@ import junit.framework.Test;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils; import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.AnalyzingUtils; import org.jetbrains.jet.lang.resolve.AnalyzingUtils;
@@ -93,7 +93,7 @@ public class QuickJetPsiCheckerTest extends JetLiteFixture {
// } // }
public static Test suite() { public static Test suite() {
return JetTestCaseBase.suiteForDirectory(JetTestCaseBase.getTestDataPathBase(), "/checkerWithErrorTypes/quick", true, new JetTestCaseBase.NamedTestFactory() { return JetTestCaseBuilder.suiteForDirectory(JetTestCaseBuilder.getTestDataPathBase(), "/checkerWithErrorTypes/quick", true, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull @NotNull
@Override @Override
public Test createTest(@NotNull String dataPath, @NotNull String name) { public Test createTest(@NotNull String dataPath, @NotNull String name) {
@@ -20,7 +20,6 @@ import java.util.Map;
*/ */
public abstract class CodegenTestCase extends JetLiteFixture { public abstract class CodegenTestCase extends JetLiteFixture {
private MyClassLoader myClassLoader; private MyClassLoader myClassLoader;
private JetFile myFile;
protected static void assertThrows(Method foo, Class<? extends Throwable> exceptionClass, Object instance, Object... args) throws IllegalAccessException { protected static void assertThrows(Method foo, Class<? extends Throwable> exceptionClass, Object instance, Object... args) throws IllegalAccessException {
boolean caught = false; boolean caught = false;
@@ -26,6 +26,41 @@ public class FunctionGenTest extends CodegenTestCase {
} }
public void testNullableAnyToString () 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 testNullableStringPlus () throws InvocationTargetException, IllegalAccessException {
loadText("fun foo(x: String?, y: Any?) = x + y");
String text = generateToText();
assertTrue(text.contains(".stringPlus"));
System.out.println(text);
Method foo = generateFunction();
assertEquals("something239", foo.invoke(null, "something", 239));
assertEquals("null239", foo.invoke(null, null, 239));
assertEquals("239null", foo.invoke(null, "239", null));
assertEquals("nullnull", foo.invoke(null, null, null));
}
public void testNonNullableStringPlus () throws InvocationTargetException, IllegalAccessException {
loadText("fun foo(x: String, y: Any?) = x + y + 120");
String text = generateToText();
assertFalse(text.contains(".stringPlus"));
System.out.println(text);
Method foo = generateFunction();
assertEquals("something239120", foo.invoke(null, "something", 239));
assertEquals("null239120", foo.invoke(null, null, 239));
assertEquals("239null120", foo.invoke(null, "239", null));
assertEquals("nullnull120", foo.invoke(null, null, null));
}
public void testAnyEqualsNullable () throws InvocationTargetException, IllegalAccessException { public void testAnyEqualsNullable () throws InvocationTargetException, IllegalAccessException {
loadText("fun foo(x: Any?) = x.equals(\"lala\")"); loadText("fun foo(x: Any?) = x.equals(\"lala\")");
System.out.println(generateToText()); System.out.println(generateToText());
@@ -41,4 +76,8 @@ public class FunctionGenTest extends CodegenTestCase {
assertTrue((Boolean) foo.invoke(null, "lala")); assertTrue((Boolean) foo.invoke(null, "lala"));
assertFalse((Boolean) foo.invoke(null, "mama")); assertFalse((Boolean) foo.invoke(null, "mama"));
} }
public void testKt395 () {
blackBoxFile("regressions/kt395.jet");
}
} }
@@ -169,25 +169,25 @@ public class PrimitiveTypesTest extends CodegenTestCase {
} }
public void testPreDecrement() throws Exception { public void testPreDecrement() throws Exception {
loadText("fun foo(a: Int): Int { return --a;}"); loadText("fun foo(var a: Int): Int { return --a;}");
final Method main = generateFunction(); final Method main = generateFunction();
assertEquals(9, main.invoke(null, 10)); assertEquals(9, main.invoke(null, 10));
} }
public void testPreIncrementLong() throws Exception { public void testPreIncrementLong() throws Exception {
loadText("fun foo(a: Long): Long = ++a"); loadText("fun foo(var a: Long): Long = ++a");
final Method main = generateFunction(); final Method main = generateFunction();
assertEquals(11L, main.invoke(null, 10L)); assertEquals(11L, main.invoke(null, 10L));
} }
public void testPreIncrementFloat() throws Exception { public void testPreIncrementFloat() throws Exception {
loadText("fun foo(a: Float): Float = ++a"); loadText("fun foo(var a: Float): Float = ++a");
final Method main = generateFunction(); final Method main = generateFunction();
assertEquals(2.0f, main.invoke(null, 1.0f)); assertEquals(2.0f, main.invoke(null, 1.0f));
} }
public void testPreIncrementDouble() throws Exception { public void testPreIncrementDouble() throws Exception {
loadText("fun foo(a: Double): Double = ++a"); loadText("fun foo(var a: Double): Double = ++a");
final Method main = generateFunction(); final Method main = generateFunction();
assertEquals(2.0, main.invoke(null, 1.0)); assertEquals(2.0, main.invoke(null, 1.0));
} }
@@ -13,7 +13,7 @@ import junit.framework.Test;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.lang.parsing.JetParserDefinition; import org.jetbrains.jet.lang.parsing.JetParserDefinition;
import org.jetbrains.jet.lang.psi.JetElement; import org.jetbrains.jet.lang.psi.JetElement;
import org.jetbrains.jet.lang.psi.JetVisitorVoid; import org.jetbrains.jet.lang.psi.JetVisitorVoid;
@@ -101,7 +101,7 @@ public class JetParsingTest extends ParsingTestCase {
public static TestSuite suite() { public static TestSuite suite() {
TestSuite suite = new TestSuite(); TestSuite suite = new TestSuite();
JetTestCaseBase.NamedTestFactory factory = new JetTestCaseBase.NamedTestFactory() { JetTestCaseBuilder.NamedTestFactory factory = new JetTestCaseBuilder.NamedTestFactory() {
@NotNull @NotNull
@Override @Override
public Test createTest(@NotNull String dataPath, @NotNull String name) { public Test createTest(@NotNull String dataPath, @NotNull String name) {
@@ -109,8 +109,8 @@ public class JetParsingTest extends ParsingTestCase {
} }
}; };
String prefix = JetParsingTest.getTestDataDir() + "/psi/"; String prefix = JetParsingTest.getTestDataDir() + "/psi/";
suite.addTest(JetTestCaseBase.suiteForDirectory(prefix, "/", false, factory)); suite.addTest(JetTestCaseBuilder.suiteForDirectory(prefix, "/", false, factory));
suite.addTest(JetTestCaseBase.suiteForDirectory(prefix, "examples", true, factory)); suite.addTest(JetTestCaseBuilder.suiteForDirectory(prefix, "examples", true, factory));
return suite; return suite;
} }
@@ -1,7 +1,5 @@
package org.jetbrains.jet.resolve; package org.jetbrains.jet.resolve;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
@@ -48,17 +46,7 @@ public class ExpectedResolveData {
// this.nameToType = nameToType; // this.nameToType = nameToType;
} }
public void extractData(final Document document) { public String extractData(String text) {
new WriteCommandAction.Simple(null) {
public void run() {
doExtractData(document);
}
}.execute().throwException();
}
private void doExtractData(Document document) {
String text = document.getText();
Pattern pattern = Pattern.compile("(~[^~]+~)|(`[^`]+`)"); Pattern pattern = Pattern.compile("(~[^~]+~)|(`[^`]+`)");
while (true) { while (true) {
Matcher matcher = pattern.matcher(text); Matcher matcher = pattern.matcher(text);
@@ -84,11 +72,11 @@ public class ExpectedResolveData {
throw new IllegalStateException(); throw new IllegalStateException();
} }
document.replaceString(start, matcher.end(), ""); text = text.substring(0, start) + text.substring(matcher.end());
text = document.getText();
} }
System.out.println(text); System.out.println(text);
return text;
} }
public void checkResult(JetFile file) { public void checkResult(JetFile file) {
@@ -1,108 +1,29 @@
package org.jetbrains.jet.resolve; package org.jetbrains.jet.resolve;
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.testFramework.FileTreeAccessFilter;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import java.util.Collection; import java.io.File;
import java.util.List;
/** /**
* @author abreslav * @author abreslav
*/ */
public abstract class ExtensibleResolveTestCase extends LightCodeInsightTestCase { public abstract class ExtensibleResolveTestCase extends JetLiteFixture {
private final FileTreeAccessFilter myJavaFilesFilter = new FileTreeAccessFilter();
private ExpectedResolveData expectedResolveData; private ExpectedResolveData expectedResolveData;
@Override @Override
protected void setUp() throws Exception { protected void setUp() throws Exception {
super.setUp(); super.setUp();
expectedResolveData = getExpectedResolveData(); expectedResolveData = getExpectedResolveData();
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).prepareForTest();
DaemonCodeAnalyzerSettings.getInstance().setImportHintEnabled(false);
} }
protected abstract ExpectedResolveData getExpectedResolveData(); protected abstract ExpectedResolveData getExpectedResolveData();
@Override protected void doTest(@NonNls String filePath) throws Exception {
protected void tearDown() throws Exception { String text = loadFile(filePath);
((DaemonCodeAnalyzerImpl) DaemonCodeAnalyzer.getInstance(getProject())).cleanupAfterTest(false); // has to cleanup by hand since light project does not get disposed any time soon text = expectedResolveData.extractData(text);
super.tearDown(); JetFile jetFile = createPsiFile(new File(filePath).getName(), text);
} expectedResolveData.checkResult(jetFile);
@Override
protected void runTest() throws Throwable {
final Throwable[] throwable = {null};
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
try {
doRunTest();
} catch (Throwable t) {
throwable[0] = t;
}
}
}, "", null);
if (throwable[0] != null) {
throw throwable[0];
}
}
protected void doTest(@NonNls String filePath, boolean checkWarnings, boolean checkInfos) throws Exception {
configureByFile(filePath);
doTestConfiguredFile(checkWarnings, checkInfos);
}
protected void doTestConfiguredFile(boolean checkWarnings, boolean checkInfos) {
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
// ExpectedHighlightingData expectedData = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkInfos);
expectedResolveData.extractData(getEditor().getDocument());
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
getFile().getText(); //to load text
myJavaFilesFilter.allowTreeAccessForFile(getVFile());
getJavaFacade().setAssertOnFileLoadingFilter(myJavaFilesFilter); // check repository work
Collection<HighlightInfo> infos = doHighlighting();
getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
expectedResolveData.checkResult((JetFile) getFile());
}
@NotNull
protected List<HighlightInfo> doHighlighting() {
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
int[] toIgnore = doFolding() ? ArrayUtil.EMPTY_INT_ARRAY : new int[]{Pass.UPDATE_FOLDING};
Editor editor = getEditor();
PsiFile file = getFile();
if (editor instanceof EditorWindow) {
editor = ((EditorWindow) editor).getDelegate();
file = InjectedLanguageUtil.getTopLevelFile(file);
}
return CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, toIgnore, false);
}
protected boolean doFolding() {
return false;
} }
} }
@@ -2,7 +2,6 @@ package org.jetbrains.jet.resolve;
import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
@@ -10,7 +9,7 @@ import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope;
import junit.framework.Test; import junit.framework.Test;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
@@ -133,10 +132,12 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
return getHomeDirectory() + "/compiler/testData"; return getHomeDirectory() + "/compiler/testData";
} }
/*
@Override @Override
protected Sdk getProjectJDK() { protected Sdk getProjectJDK() {
return JetTestCaseBase.jdkFromIdeaHome(); return PluginTestCaseBase.jdkFromIdeaHome();
} }
*/
private static String getHomeDirectory() { private static String getHomeDirectory() {
return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent(); return new File(PathManager.getResourceRoot(JetParsingTest.class, "/org/jetbrains/jet/parsing/JetParsingTest.class")).getParentFile().getParentFile().getParent();
@@ -149,11 +150,11 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
@Override @Override
protected void runTest() throws Throwable { protected void runTest() throws Throwable {
doTest(path, true, false); doTest(path);
} }
public static Test suite() { public static Test suite() {
return JetTestCaseBase.suiteForDirectory(getHomeDirectory() + "/compiler/testData/", "/resolve/", true, new JetTestCaseBase.NamedTestFactory() { return JetTestCaseBuilder.suiteForDirectory(getHomeDirectory() + "/compiler/testData/", "/resolve/", true, new JetTestCaseBuilder.NamedTestFactory() {
@NotNull @NotNull
@Override @Override
public Test createTest(@NotNull String dataPath, @NotNull String name) { public Test createTest(@NotNull String dataPath, @NotNull String name) {
@@ -1,7 +1,7 @@
package org.jetbrains.jet.types; package org.jetbrains.jet.types;
import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
@@ -32,7 +32,7 @@ public class JetOverridingTest extends JetLiteFixture {
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() {
return JetTestCaseBase.getTestDataPathBase(); return JetTestCaseBuilder.getTestDataPathBase();
} }
public void testBasic() throws Exception { public void testBasic() throws Exception {
@@ -5,7 +5,7 @@ import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetLiteFixture; import org.jetbrains.jet.JetLiteFixture;
import org.jetbrains.jet.JetTestCaseBase; import org.jetbrains.jet.JetTestCaseBuilder;
import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.lang.JetSemanticServices; import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
@@ -51,7 +51,7 @@ public class JetTypeCheckerTest extends JetLiteFixture {
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() {
return JetTestCaseBase.getTestDataPathBase(); return JetTestCaseBuilder.getTestDataPathBase();
} }
public void testConstants() throws Exception { public void testConstants() throws Exception {
@@ -10,6 +10,6 @@ import org.jetbrains.annotations.NotNull;
public class JetFileFactory extends FileTypeFactory { public class JetFileFactory extends FileTypeFactory {
@Override @Override
public void createFileTypes(@NotNull FileTypeConsumer consumer) { public void createFileTypes(@NotNull FileTypeConsumer consumer) {
consumer.consume(JetFileType.INSTANCE, "jet;jetl;jets;kt"); consumer.consume(JetFileType.INSTANCE, "jet;jetl;jets;kt;kts;ktm");
} }
} }
@@ -52,7 +52,7 @@ abstract class Sum() : Iteratee<Int, Int> {
} }
abstract class Collection<E> : Iterable<E> { abstract class Collection<E> : Iterable<E> {
fun iterate<O>(iteratee : Iteratee<E, O>) : O { fun iterate<O>(var iteratee : Iteratee<E, O>) : O {
for (x in this) { for (x in this) {
val it = iteratee.process(x) val it = iteratee.process(x)
if (it.isDone) return it.result if (it.isDone) return it.result
@@ -1,4 +1,4 @@
class Foo(var bar : Int, barr : Int, val barrr : Int) { class Foo(var bar : Int, var barr : Int, var barrr : Int) {
{ {
bar = 1 bar = 1
barr = 1 barr = 1
@@ -7,7 +7,7 @@
this : Foo this : Foo
} }
this(val bar : Int) : this(1, 1, 1) { this(var bar : Int) : this(1, 1, 1) {
bar = 1 bar = 1
this.bar this.bar
1 : Int 1 : Int

Some files were not shown because too many files have changed in this diff Show More