Special instructions added for calls and other constructs
This commit is contained in:
@@ -19,7 +19,11 @@ package org.jetbrains.jet.lang.cfg;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -82,7 +86,24 @@ public interface JetControlFlowBuilder {
|
||||
|
||||
// Reading values
|
||||
void loadUnit(@NotNull JetExpression expression);
|
||||
void read(@NotNull JetElement element);
|
||||
void loadConstant(@NotNull JetExpression expression, @Nullable CompileTimeConstant<?> constant);
|
||||
void createAnonymousObject(@NotNull JetObjectLiteralExpression expression);
|
||||
void loadStringTemplate(@NotNull JetStringTemplateExpression expression);
|
||||
|
||||
void readThis(@NotNull JetExpression expression, @Nullable ReceiverParameterDescriptor parameterDescriptor);
|
||||
void readVariable(@NotNull JetExpression expression, @Nullable VariableDescriptor variableDescriptor);
|
||||
|
||||
void call(@NotNull JetExpression expression, @NotNull ResolvedCall<?> resolvedCall);
|
||||
|
||||
enum PredefinedOperation {
|
||||
AND,
|
||||
OR,
|
||||
NOT_NULL_ASSERTION
|
||||
}
|
||||
void predefinedOperation(@NotNull JetExpression expression, @Nullable PredefinedOperation operation);
|
||||
|
||||
void compilationError(@NotNull JetElement element, @NotNull String message);
|
||||
|
||||
void write(@NotNull JetElement assignment, @NotNull JetElement lValue);
|
||||
|
||||
// Other
|
||||
|
||||
@@ -19,7 +19,11 @@ package org.jetbrains.jet.lang.cfg;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -27,13 +31,48 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
|
||||
protected JetControlFlowBuilder builder;
|
||||
|
||||
@Override
|
||||
public void read(@NotNull JetElement element) {
|
||||
builder.read(element);
|
||||
public void loadUnit(@NotNull JetExpression expression) {
|
||||
builder.loadUnit(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadUnit(@NotNull JetExpression expression) {
|
||||
builder.loadUnit(expression);
|
||||
public void loadConstant(@NotNull JetExpression expression, @Nullable CompileTimeConstant<?> constant) {
|
||||
builder.loadConstant(expression, constant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAnonymousObject(@NotNull JetObjectLiteralExpression expression) {
|
||||
builder.createAnonymousObject(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadStringTemplate(@NotNull JetStringTemplateExpression expression) {
|
||||
builder.loadStringTemplate(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readThis(@NotNull JetExpression expression, @Nullable ReceiverParameterDescriptor parameterDescriptor) {
|
||||
builder.readThis(expression, parameterDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readVariable(@NotNull JetExpression expression, @Nullable VariableDescriptor variableDescriptor) {
|
||||
builder.readVariable(expression, variableDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(@NotNull JetExpression expression, @NotNull ResolvedCall<?> resolvedCall) {
|
||||
builder.call(expression, resolvedCall);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void predefinedOperation(@NotNull JetExpression expression, @Nullable PredefinedOperation operation) {
|
||||
builder.predefinedOperation(expression, operation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compilationError(@NotNull JetElement element, @NotNull String message) {
|
||||
builder.compilationError(element, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,21 +26,35 @@ import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowInstructionsGenerator
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.LocalFunctionDeclarationInstruction;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.Pseudocode;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.PseudocodeImpl;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.constants.BooleanValue;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.lexer.JetToken;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.jet.lang.cfg.JetControlFlowBuilder.PredefinedOperation.*;
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
|
||||
public class JetControlFlowProcessor {
|
||||
@@ -153,8 +167,6 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitParenthesizedExpression(@NotNull JetParenthesizedExpression expression) {
|
||||
builder.read(expression);
|
||||
|
||||
JetExpression innerExpression = expression.getExpression();
|
||||
if (innerExpression != null) {
|
||||
generateInstructions(innerExpression, inCondition);
|
||||
@@ -163,8 +175,6 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitAnnotatedExpression(@NotNull JetAnnotatedExpression expression) {
|
||||
builder.read(expression);
|
||||
|
||||
JetExpression baseExpression = expression.getBaseExpression();
|
||||
if (baseExpression != null) {
|
||||
generateInstructions(baseExpression, inCondition);
|
||||
@@ -173,17 +183,26 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitThisExpression(@NotNull JetThisExpression expression) {
|
||||
builder.read(expression);
|
||||
ResolvedCall<?> resolvedCall = getResolvedCall(expression);
|
||||
builder.readThis(expression, resolvedCall == null ? null : (ReceiverParameterDescriptor) resolvedCall.getResultingDescriptor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConstantExpression(@NotNull JetConstantExpression expression) {
|
||||
builder.read(expression);
|
||||
CompileTimeConstant<?> constant = trace.get(BindingContext.COMPILE_TIME_VALUE, expression);
|
||||
builder.loadConstant(expression, constant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression) {
|
||||
builder.read(expression);
|
||||
ResolvedCall<?> resolvedCall = getResolvedCall(expression);
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||
generateCall(expression, variableAsFunctionResolvedCall.getVariableCall());
|
||||
}
|
||||
else {
|
||||
generateCall(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -204,7 +223,8 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@SuppressWarnings("SuspiciousMethodCalls") @Override
|
||||
public void visitBinaryExpression(@NotNull JetBinaryExpression expression) {
|
||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||
JetSimpleNameExpression operationReference = expression.getOperationReference();
|
||||
IElementType operationType = operationReference.getReferencedNameElementType();
|
||||
JetExpression right = expression.getRight();
|
||||
if (operationType == JetTokens.ANDAND) {
|
||||
generateInstructions(expression.getLeft(), true);
|
||||
@@ -215,7 +235,7 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
builder.bindLabel(resultLabel);
|
||||
if (!inCondition) {
|
||||
builder.read(expression);
|
||||
builder.predefinedOperation(expression, AND);
|
||||
}
|
||||
}
|
||||
else if (operationType == JetTokens.OROR) {
|
||||
@@ -227,51 +247,33 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
builder.bindLabel(resultLabel);
|
||||
if (!inCondition) {
|
||||
builder.read(expression);
|
||||
builder.predefinedOperation(expression, OR);
|
||||
}
|
||||
}
|
||||
else if (operationType == JetTokens.EQ) {
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
if (right != null) {
|
||||
generateInstructions(right, false);
|
||||
}
|
||||
if (left instanceof JetSimpleNameExpression) {
|
||||
builder.write(expression, left);
|
||||
}
|
||||
else if (left instanceof JetArrayAccessExpression) {
|
||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
||||
visitAssignToArrayAccess(expression, arrayAccessExpression);
|
||||
}
|
||||
else if (left instanceof JetQualifiedExpression) {
|
||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression) left;
|
||||
generateInstructions(qualifiedExpression.getReceiverExpression(), false);
|
||||
generateInstructions(expression.getOperationReference(), false);
|
||||
builder.write(expression, left);
|
||||
}
|
||||
else {
|
||||
builder.unsupported(expression); // TODO
|
||||
}
|
||||
visitAssignment(expression.getLeft(), expression);
|
||||
}
|
||||
else if (OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
if (left != null) {
|
||||
generateInstructions(left, false);
|
||||
if (generateCall(operationReference)) {
|
||||
ResolvedCall<?> resolvedCall = getResolvedCall(operationReference);
|
||||
assert resolvedCall != null : "Generation succeeded, but no call is found: " + expression.getText();
|
||||
CallableDescriptor descriptor = resolvedCall.getResultingDescriptor();
|
||||
Name assignMethodName = OperatorConventions.getNameForOperationSymbol((JetToken) expression.getOperationToken());
|
||||
if (!descriptor.getName().equals(assignMethodName)) {
|
||||
// plus() called, assignment needed
|
||||
visitAssignment(expression.getLeft(), expression);
|
||||
}
|
||||
}
|
||||
if (right != null) {
|
||||
generateInstructions(right, false);
|
||||
}
|
||||
if (left instanceof JetSimpleNameExpression || left instanceof JetArrayAccessExpression) {
|
||||
generateInstructions(expression.getOperationReference(), false);
|
||||
builder.write(expression, left);
|
||||
}
|
||||
else if (left != null) {
|
||||
builder.unsupported(expression); // TODO
|
||||
else {
|
||||
generateBothArguments(expression);
|
||||
}
|
||||
}
|
||||
else if (operationType == JetTokens.ELVIS) {
|
||||
builder.read(expression);
|
||||
generateInstructions(expression.getLeft(), false);
|
||||
generateInstructions(expression.getOperationReference(), false);
|
||||
generateInstructions(operationReference, false);
|
||||
Label afterElvis = builder.createUnboundLabel();
|
||||
builder.jumpOnTrue(afterElvis);
|
||||
if (right != null) {
|
||||
@@ -280,22 +282,60 @@ public class JetControlFlowProcessor {
|
||||
builder.bindLabel(afterElvis);
|
||||
}
|
||||
else {
|
||||
generateInstructions(expression.getLeft(), false);
|
||||
if (right != null) {
|
||||
generateInstructions(right, false);
|
||||
if (!generateCall(operationReference)) {
|
||||
generateBothArguments(expression);
|
||||
}
|
||||
generateInstructions(expression.getOperationReference(), false);
|
||||
builder.read(expression);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitAssignToArrayAccess(JetBinaryExpression expression, JetArrayAccessExpression arrayAccessExpression) {
|
||||
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
|
||||
generateInstructions(index, false);
|
||||
private void generateBothArguments(JetBinaryExpression expression) {
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
if (left != null) {
|
||||
generateInstructions(left, false);
|
||||
}
|
||||
JetExpression right = expression.getRight();
|
||||
if (right != null) {
|
||||
generateInstructions(right, false);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitAssignment(JetExpression lhs, JetExpression parentExpression) {
|
||||
JetExpression left = JetPsiUtil.deparenthesize(lhs);
|
||||
if (left == null) {
|
||||
builder.compilationError(lhs, "No lValue in assignment");
|
||||
return;
|
||||
}
|
||||
if (left instanceof JetSimpleNameExpression) {
|
||||
// Do nothing, only record write below
|
||||
}
|
||||
else if (left instanceof JetArrayAccessExpression) {
|
||||
generateArrayAccess((JetArrayAccessExpression) left);
|
||||
}
|
||||
else if (left instanceof JetQualifiedExpression) {
|
||||
// read the receiver
|
||||
generateInstructions(((JetQualifiedExpression) left).getReceiverExpression(), false);
|
||||
}
|
||||
else if (left instanceof JetProperty) {
|
||||
// do nothing, just write below
|
||||
}
|
||||
else {
|
||||
builder.unsupported(parentExpression); // TODO
|
||||
}
|
||||
|
||||
VariableDescriptor descriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), left, false);
|
||||
if (descriptor != null) {
|
||||
builder.write(parentExpression, left);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateArrayAccess(JetArrayAccessExpression arrayAccessExpression) {
|
||||
if (!generateCall(arrayAccessExpression)) {
|
||||
for (JetExpression index : arrayAccessExpression.getIndexExpressions()) {
|
||||
generateInstructions(index, false);
|
||||
}
|
||||
|
||||
generateInstructions(arrayAccessExpression.getArrayExpression(), false);
|
||||
}
|
||||
generateInstructions(arrayAccessExpression.getArrayExpression(), false);
|
||||
generateInstructions(expression.getOperationReference(), false);
|
||||
builder.write(expression, arrayAccessExpression); // TODO : ???
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -308,16 +348,20 @@ public class JetControlFlowProcessor {
|
||||
String referencedName = operationSign.getReferencedName();
|
||||
visitLabeledExpression(referencedName.substring(1), baseExpression);
|
||||
}
|
||||
else {
|
||||
else if (JetTokens.EXCLEXCL == operationType) {
|
||||
generateInstructions(baseExpression, false);
|
||||
generateInstructions(operationSign, false);
|
||||
builder.predefinedOperation(expression, NOT_NULL_ASSERTION);
|
||||
}
|
||||
else {
|
||||
if (!generateCall(expression.getOperationReference())) {
|
||||
generateInstructions(baseExpression, false);
|
||||
}
|
||||
|
||||
boolean incrementOrDecrement = isIncrementOrDecrement(operationType);
|
||||
if (incrementOrDecrement) {
|
||||
builder.write(expression, baseExpression);
|
||||
// We skip dup's and other subtleties here
|
||||
visitAssignment(baseExpression, expression);
|
||||
}
|
||||
|
||||
builder.read(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,7 +397,7 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
builder.bindLabel(resultLabel);
|
||||
}
|
||||
|
||||
|
||||
private class FinallyBlockGenerator {
|
||||
private final JetFinallySection finallyBlock;
|
||||
private Label startFinally = null;
|
||||
@@ -382,7 +426,6 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitTryExpression(@NotNull JetTryExpression expression) {
|
||||
builder.read(expression);
|
||||
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||
final FinallyBlockGenerator finallyBlockGenerator = new FinallyBlockGenerator(finallyBlock);
|
||||
if (finallyBlock != null) {
|
||||
@@ -414,7 +457,6 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
generateInstructions(expression.getTryBlock(), inCondition);
|
||||
|
||||
Collection<Label> allowDeadLabels = Lists.newArrayList();
|
||||
if (hasCatches) {
|
||||
Label afterCatches = builder.createUnboundLabel("afterCatches");
|
||||
builder.jump(afterCatches);
|
||||
@@ -467,7 +509,6 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitWhileExpression(@NotNull JetWhileExpression expression) {
|
||||
builder.read(expression);
|
||||
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
|
||||
|
||||
builder.bindLabel(loopInfo.getConditionEntryPoint());
|
||||
@@ -498,7 +539,6 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitDoWhileExpression(@NotNull JetDoWhileExpression expression) {
|
||||
builder.read(expression);
|
||||
LoopInfo loopInfo = builder.enterLoop(expression, null, null);
|
||||
|
||||
builder.bindLabel(loopInfo.getBodyEntryPoint());
|
||||
@@ -518,7 +558,6 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitForExpression(@NotNull JetForExpression expression) {
|
||||
builder.read(expression);
|
||||
JetExpression loopRange = expression.getLoopRange();
|
||||
if (loopRange != null) {
|
||||
generateInstructions(loopRange, false);
|
||||
@@ -657,42 +696,32 @@ public class JetControlFlowProcessor {
|
||||
public void visitFunctionLiteralExpression(@NotNull JetFunctionLiteralExpression expression) {
|
||||
JetFunctionLiteral functionLiteral = expression.getFunctionLiteral();
|
||||
processLocalDeclaration(functionLiteral);
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitQualifiedExpression(@NotNull JetQualifiedExpression expression) {
|
||||
generateInstructions(expression.getReceiverExpression(), false);
|
||||
JetExpression selectorExpression = expression.getSelectorExpression();
|
||||
if (selectorExpression != null) {
|
||||
generateInstructions(selectorExpression, false);
|
||||
}
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
private void visitCall(JetCallElement call) {
|
||||
for (ValueArgument argument : call.getValueArguments()) {
|
||||
JetExpression argumentExpression = argument.getArgumentExpression();
|
||||
if (argumentExpression != null) {
|
||||
generateInstructions(argumentExpression, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (JetExpression functionLiteral : call.getFunctionLiteralArguments()) {
|
||||
generateInstructions(functionLiteral, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCallExpression(@NotNull JetCallExpression expression) {
|
||||
for (JetTypeProjection typeArgument : expression.getTypeArguments()) {
|
||||
generateInstructions(typeArgument, false);
|
||||
if (!generateCall(expression.getCalleeExpression())) {
|
||||
for (ValueArgument argument : expression.getValueArguments()) {
|
||||
JetExpression argumentExpression = argument.getArgumentExpression();
|
||||
if (argumentExpression != null) {
|
||||
generateInstructions(argumentExpression, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (JetExpression functionLiteral : expression.getFunctionLiteralArguments()) {
|
||||
generateInstructions(functionLiteral, false);
|
||||
}
|
||||
|
||||
generateInstructions(expression.getCalleeExpression(), false);
|
||||
}
|
||||
|
||||
visitCall(expression);
|
||||
|
||||
generateInstructions(expression.getCalleeExpression(), false);
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -701,7 +730,7 @@ public class JetControlFlowProcessor {
|
||||
JetExpression initializer = property.getInitializer();
|
||||
if (initializer != null) {
|
||||
generateInstructions(initializer, false);
|
||||
builder.write(property, property);
|
||||
visitAssignment(property, property);
|
||||
}
|
||||
JetExpression delegate = property.getDelegateExpression();
|
||||
if (delegate != null) {
|
||||
@@ -721,6 +750,10 @@ public class JetControlFlowProcessor {
|
||||
List<JetMultiDeclarationEntry> entries = declaration.getEntries();
|
||||
for (JetMultiDeclarationEntry entry : entries) {
|
||||
builder.declareVariable(entry);
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = trace.get(BindingContext.COMPONENT_RESOLVED_CALL, entry);
|
||||
if (resolvedCall != null) {
|
||||
builder.call(entry, resolvedCall);
|
||||
}
|
||||
builder.write(entry, entry);
|
||||
}
|
||||
}
|
||||
@@ -735,7 +768,6 @@ public class JetControlFlowProcessor {
|
||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||
if (operationType == JetTokens.COLON || operationType == JetTokens.AS_KEYWORD || operationType == JetTokens.AS_SAFE) {
|
||||
generateInstructions(expression.getLeft(), false);
|
||||
builder.read(expression);
|
||||
}
|
||||
else {
|
||||
visitJetElement(expression);
|
||||
@@ -753,20 +785,14 @@ public class JetControlFlowProcessor {
|
||||
|
||||
@Override
|
||||
public void visitArrayAccessExpression(@NotNull JetArrayAccessExpression expression) {
|
||||
for (JetExpression index : expression.getIndexExpressions()) {
|
||||
generateInstructions(index, false);
|
||||
if (!generateCall(expression)) {
|
||||
generateArrayAccess(expression);
|
||||
}
|
||||
generateInstructions(expression.getArrayExpression(), false);
|
||||
// TODO : read 'get' or 'set' function
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIsExpression(@NotNull JetIsExpression expression) {
|
||||
generateInstructions(expression.getLeftHandSide(), inCondition);
|
||||
// no CF for types
|
||||
// TODO : builder.read(expression.getPattern());
|
||||
builder.read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -783,8 +809,6 @@ public class JetControlFlowProcessor {
|
||||
for (Iterator<JetWhenEntry> iterator = expression.getEntries().iterator(); iterator.hasNext(); ) {
|
||||
JetWhenEntry whenEntry = iterator.next();
|
||||
|
||||
builder.read(whenEntry);
|
||||
|
||||
boolean isElse = whenEntry.isElse();
|
||||
if (isElse) {
|
||||
hasElse = true;
|
||||
@@ -837,7 +861,7 @@ public class JetControlFlowProcessor {
|
||||
for (JetDeclaration function : functions) {
|
||||
generateInstructions(function, inCondition);
|
||||
}
|
||||
builder.read(expression);
|
||||
builder.createAnonymousObject(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -853,7 +877,7 @@ public class JetControlFlowProcessor {
|
||||
generateInstructions(entryWithExpression.getExpression(), false);
|
||||
}
|
||||
}
|
||||
builder.read(expression);
|
||||
builder.loadStringTemplate(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -913,5 +937,79 @@ public class JetControlFlowProcessor {
|
||||
public void visitJetElement(@NotNull JetElement element) {
|
||||
builder.unsupported(element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ResolvedCall<?> getResolvedCall(@NotNull JetElement expression) {
|
||||
return trace.get(BindingContext.RESOLVED_CALL, expression);
|
||||
}
|
||||
|
||||
private boolean generateCall(JetExpression calleeExpression) {
|
||||
ResolvedCall<?> resolvedCall = getResolvedCall(calleeExpression);
|
||||
if (resolvedCall == null) {
|
||||
builder.compilationError(calleeExpression, "No resolved call");
|
||||
return false;
|
||||
}
|
||||
generateCall(calleeExpression, resolvedCall);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void generateCall(JetExpression calleeExpression, ResolvedCall<?> resolvedCall) {
|
||||
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
|
||||
VariableAsFunctionResolvedCall variableAsFunctionResolvedCall = (VariableAsFunctionResolvedCall) resolvedCall;
|
||||
generateCall(calleeExpression, variableAsFunctionResolvedCall.getFunctionCall());
|
||||
return;
|
||||
}
|
||||
|
||||
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||
if (resultingDescriptor instanceof ExpressionAsFunctionDescriptor) {
|
||||
generateInstructions(((ExpressionAsFunctionDescriptor) resultingDescriptor).getExpression(), false);
|
||||
}
|
||||
|
||||
generateReceiver(resolvedCall.getThisObject());
|
||||
generateReceiver(resolvedCall.getReceiverArgument());
|
||||
|
||||
for (ValueParameterDescriptor parameterDescriptor : resultingDescriptor.getValueParameters()) {
|
||||
ResolvedValueArgument argument = resolvedCall.getValueArguments().get(parameterDescriptor);
|
||||
if (argument == null) continue;
|
||||
|
||||
generateValueArgument(argument);
|
||||
}
|
||||
|
||||
if (resultingDescriptor instanceof VariableDescriptor) {
|
||||
builder.readVariable(calleeExpression, (VariableDescriptor) resultingDescriptor);
|
||||
}
|
||||
else {
|
||||
builder.call(calleeExpression, resolvedCall);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateReceiver(ReceiverValue receiver) {
|
||||
if (!receiver.exists()) return;
|
||||
if (receiver instanceof ThisReceiver) {
|
||||
// TODO: Receiver is passed implicitly: no expression to tie the read to
|
||||
}
|
||||
else if (receiver instanceof ExpressionReceiver) {
|
||||
generateInstructions(((ExpressionReceiver) receiver).getExpression(), false);
|
||||
}
|
||||
else if (receiver instanceof TransientReceiver) {
|
||||
// Do nothing
|
||||
}
|
||||
else if (receiver instanceof AutoCastReceiver) {
|
||||
// No cast instruction in our CFG
|
||||
generateReceiver(((AutoCastReceiver) receiver).getOriginal());
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown receiver kind: " + receiver);
|
||||
}
|
||||
}
|
||||
|
||||
private void generateValueArgument(ResolvedValueArgument argument) {
|
||||
for (ValueArgument valueArgument : argument.getArguments()) {
|
||||
JetExpression expression = valueArgument.getArgumentExpression();
|
||||
if (expression != null) {
|
||||
generateInstructions(expression, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+10
-2
@@ -80,11 +80,19 @@ public class InstructionVisitor {
|
||||
visitInstructionWithNext(instruction);
|
||||
}
|
||||
|
||||
public void visitWriteValue(WriteValueInstruction writeValueInstruction) {
|
||||
visitInstructionWithNext(writeValueInstruction);
|
||||
public void visitWriteValue(WriteValueInstruction instruction) {
|
||||
visitInstructionWithNext(instruction);
|
||||
}
|
||||
|
||||
public void visitLoadUnitValue(LoadUnitValueInstruction instruction) {
|
||||
visitInstructionWithNext(instruction);
|
||||
}
|
||||
|
||||
public void visitCallInstruction(CallInstruction instruction) {
|
||||
visitInstructionWithNext(instruction);
|
||||
}
|
||||
|
||||
public void visitCompilationErrorInstruction(CompilationErrorInstruction instruction) {
|
||||
visitInstructionWithNext(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
+49
-6
@@ -20,7 +20,11 @@ import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.cfg.*;
|
||||
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -251,11 +255,6 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
add(new LocalFunctionDeclarationInstruction(subroutine, pseudocode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(@NotNull JetElement element) {
|
||||
add(new ReadValueInstruction(element));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadUnit(@NotNull JetExpression expression) {
|
||||
add(new LoadUnitValueInstruction(expression));
|
||||
@@ -313,7 +312,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
handleJumpInsideTryFinally(error);
|
||||
add(new ThrowExceptionInstruction(expression, error));
|
||||
}
|
||||
|
||||
|
||||
public void exitTryFinally() {
|
||||
BlockInfo pop = allBlocks.pop();
|
||||
assert pop instanceof TryFinallyBlockInfo;
|
||||
@@ -328,6 +327,50 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
|
||||
public void repeatPseudocode(@NotNull Label startLabel, @NotNull Label finishLabel) {
|
||||
pseudocode.repeatPart(startLabel, finishLabel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadConstant(@NotNull JetExpression expression, @Nullable CompileTimeConstant<?> constant) {
|
||||
read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAnonymousObject(@NotNull JetObjectLiteralExpression expression) {
|
||||
read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadStringTemplate(@NotNull JetStringTemplateExpression expression) {
|
||||
read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readThis(@NotNull JetExpression expression, @Nullable ReceiverParameterDescriptor parameterDescriptor) {
|
||||
read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readVariable(@NotNull JetExpression expression, @Nullable VariableDescriptor variableDescriptor) {
|
||||
read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void call(@NotNull JetExpression expression, @NotNull ResolvedCall<?> resolvedCall) {
|
||||
add(new CallInstruction(expression, resolvedCall));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void predefinedOperation(@NotNull JetExpression expression, @Nullable PredefinedOperation operation) {
|
||||
read(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compilationError(@NotNull JetElement element, @NotNull String message) {
|
||||
add(new CompilationErrorInstruction(element, message));
|
||||
}
|
||||
|
||||
private void read(@NotNull JetElement element) {
|
||||
add(new ReadValueInstruction(element));
|
||||
}
|
||||
}
|
||||
|
||||
public static class TryFinallyBlockInfo extends BlockInfo {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.lang.cfg.pseudocode
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
|
||||
|
||||
class CallInstruction(
|
||||
element: JetElement,
|
||||
val resolvedCall: ResolvedCall<*>
|
||||
) : InstructionWithNext(element) {
|
||||
|
||||
override fun accept(visitor: InstructionVisitor) {
|
||||
visitor.visitCallInstruction(this)
|
||||
}
|
||||
|
||||
override fun createCopy() = CallInstruction(element, resolvedCall)
|
||||
|
||||
override fun toString() = "call(${element.getText()}, ${resolvedCall.getResultingDescriptor()!!.getName()})"
|
||||
}
|
||||
|
||||
class CompilationErrorInstruction(
|
||||
element: JetElement,
|
||||
val message: String
|
||||
) : InstructionWithNext(element) {
|
||||
|
||||
override fun accept(visitor: InstructionVisitor) {
|
||||
visitor.visitCompilationErrorInstruction(this)
|
||||
}
|
||||
|
||||
override fun createCopy() = CompilationErrorInstruction(element, message)
|
||||
|
||||
override fun toString() = "error(${element.getText()}, $message)"
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
== Ab ==
|
||||
abstract class Ab {
|
||||
abstract fun getArray() : Array<Int>
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
<START> NEXT:[<END>] PREV:[]
|
||||
L1:
|
||||
<END> NEXT:[<SINK>] PREV:[<START>]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== test ==
|
||||
fun test(ab: Ab) {
|
||||
ab.getArray()[1]
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
<START> NEXT:[v(ab: Ab)] PREV:[]
|
||||
v(ab: Ab) NEXT:[w(ab)] PREV:[<START>]
|
||||
w(ab) NEXT:[r(ab)] PREV:[v(ab: Ab)]
|
||||
r(ab) NEXT:[call(getArray, getArray)] PREV:[w(ab)]
|
||||
call(getArray, getArray) NEXT:[r(1)] PREV:[r(ab)]
|
||||
r(1) NEXT:[call(ab.getArray()[1], get)] PREV:[call(getArray, getArray)]
|
||||
call(ab.getArray()[1], get) NEXT:[<END>] PREV:[r(1)]
|
||||
L1:
|
||||
<END> NEXT:[<SINK>] PREV:[call(ab.getArray()[1], get)]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
abstract class Ab {
|
||||
abstract fun getArray() : Array<Int>
|
||||
}
|
||||
|
||||
fun test(ab: Ab) {
|
||||
ab.getArray()[1]
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
== C ==
|
||||
class C {
|
||||
val a: Int
|
||||
get() = 1
|
||||
|
||||
{
|
||||
$a
|
||||
}
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
<START> NEXT:[v(val a: Int get() = 1) ] PREV:[]
|
||||
v(val a: Int
|
||||
get() = 1) NEXT:[jmp?(L2)] PREV:[<START>]
|
||||
jmp?(L2) NEXT:[r($a), d(get() = 1)] PREV:[v(val a: Int get() = 1) ]
|
||||
d(get() = 1) NEXT:[<SINK>] PREV:[jmp?(L2)]
|
||||
L2:
|
||||
r($a) NEXT:[<END>] PREV:[jmp?(L2)]
|
||||
L1:
|
||||
<END> NEXT:[<SINK>] PREV:[r($a)]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>, d(get() = 1)]
|
||||
L3:
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[<END>] PREV:[<START>]
|
||||
L4:
|
||||
<END> NEXT:[<SINK>] PREV:[r(1)]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
== get_a ==
|
||||
get() = 1
|
||||
---------------------
|
||||
L3:
|
||||
<START> NEXT:[r(1)] PREV:[]
|
||||
r(1) NEXT:[<END>] PREV:[<START>]
|
||||
L4:
|
||||
<END> NEXT:[<SINK>] PREV:[r(1)]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
@@ -0,0 +1,8 @@
|
||||
class C {
|
||||
val a: Int
|
||||
get() = 1
|
||||
|
||||
{
|
||||
$a
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
== foo ==
|
||||
fun foo() {
|
||||
var i = 1
|
||||
i++
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
<START> NEXT:[v(var i = 1)] PREV:[]
|
||||
v(var i = 1) NEXT:[r(1)] PREV:[<START>]
|
||||
r(1) NEXT:[w(i)] PREV:[v(var i = 1)]
|
||||
w(i) NEXT:[r(i)] PREV:[r(1)]
|
||||
r(i) NEXT:[call(++, inc)] PREV:[w(i)]
|
||||
call(++, inc) NEXT:[w(i)] PREV:[r(i)]
|
||||
w(i) NEXT:[<END>] PREV:[call(++, inc)]
|
||||
L1:
|
||||
<END> NEXT:[<SINK>] PREV:[w(i)]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
@@ -0,0 +1,4 @@
|
||||
fun foo() {
|
||||
var i = 1
|
||||
i++
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
== foo ==
|
||||
fun foo(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
<START> NEXT:[v(f: () -> Unit)] PREV:[]
|
||||
v(f: () -> Unit) NEXT:[w(f)] PREV:[<START>]
|
||||
w(f) NEXT:[r(f)] PREV:[v(f: () -> Unit)]
|
||||
r(f) NEXT:[call(f, invoke)] PREV:[w(f)]
|
||||
call(f, invoke) NEXT:[<END>] PREV:[r(f)]
|
||||
L1:
|
||||
<END> NEXT:[<SINK>] PREV:[call(f, invoke)]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
@@ -0,0 +1,3 @@
|
||||
fun foo(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
== foo ==
|
||||
fun foo(x: Int) {
|
||||
val (a, b) = x
|
||||
a
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
<START> NEXT:[v(x: Int)] PREV:[]
|
||||
v(x: Int) NEXT:[w(x)] PREV:[<START>]
|
||||
w(x) NEXT:[r(x)] PREV:[v(x: Int)]
|
||||
r(x) NEXT:[v(a)] PREV:[w(x)]
|
||||
v(a) NEXT:[w(a)] PREV:[r(x)]
|
||||
w(a) NEXT:[v(b)] PREV:[v(a)]
|
||||
v(b) NEXT:[w(b)] PREV:[w(a)]
|
||||
w(b) NEXT:[r(a)] PREV:[v(b)]
|
||||
r(a) NEXT:[<END>] PREV:[w(b)]
|
||||
L1:
|
||||
<END> NEXT:[<SINK>] PREV:[r(a)]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
@@ -0,0 +1,4 @@
|
||||
fun foo(x: Int) {
|
||||
val (a, b) = x
|
||||
a
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
== test ==
|
||||
fun test(s: String?) {
|
||||
s?.length
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
<START> NEXT:[v(s: String?)] PREV:[]
|
||||
v(s: String?) NEXT:[w(s)] PREV:[<START>]
|
||||
w(s) NEXT:[r(s)] PREV:[v(s: String?)]
|
||||
r(s) NEXT:[call(length, length)] PREV:[w(s)]
|
||||
call(length, length) NEXT:[<END>] PREV:[r(s)]
|
||||
L1:
|
||||
<END> NEXT:[<SINK>] PREV:[call(length, length)]
|
||||
error:
|
||||
<ERROR> NEXT:[<SINK>] PREV:[]
|
||||
sink:
|
||||
<SINK> NEXT:[] PREV:[<ERROR>, <END>]
|
||||
=====================
|
||||
@@ -0,0 +1,3 @@
|
||||
fun test(s: String?) {
|
||||
s?.length
|
||||
}
|
||||
@@ -110,7 +110,7 @@ class Test() {
|
||||
a++
|
||||
(@ a)++
|
||||
(a : Int)++
|
||||
(a)++
|
||||
<!UNUSED_CHANGED_VALUE!>(a)++<!>
|
||||
}
|
||||
|
||||
fun testVariables1() {
|
||||
|
||||
@@ -46,11 +46,21 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
||||
doTest("compiler/testData/cfg/ArrayAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("arrayAccessExpression.kt")
|
||||
public void testArrayAccessExpression() throws Exception {
|
||||
doTest("compiler/testData/cfg/arrayAccessExpression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Assignments.kt")
|
||||
public void testAssignments() throws Exception {
|
||||
doTest("compiler/testData/cfg/Assignments.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("backingFieldAccess.kt")
|
||||
public void testBackingFieldAccess() throws Exception {
|
||||
doTest("compiler/testData/cfg/backingFieldAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Basic.kt")
|
||||
public void testBasic() throws Exception {
|
||||
doTest("compiler/testData/cfg/Basic.kt");
|
||||
@@ -96,6 +106,16 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
||||
doTest("compiler/testData/cfg/If.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incrementAtTheEnd.kt")
|
||||
public void testIncrementAtTheEnd() throws Exception {
|
||||
doTest("compiler/testData/cfg/incrementAtTheEnd.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("invoke.kt")
|
||||
public void testInvoke() throws Exception {
|
||||
doTest("compiler/testData/cfg/invoke.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("LazyBooleans.kt")
|
||||
public void testLazyBooleans() throws Exception {
|
||||
doTest("compiler/testData/cfg/LazyBooleans.kt");
|
||||
@@ -111,6 +131,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
||||
doTest("compiler/testData/cfg/MultiDecl.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multiDeclarationWithError.kt")
|
||||
public void testMultiDeclarationWithError() throws Exception {
|
||||
doTest("compiler/testData/cfg/multiDeclarationWithError.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ObjectExpression.kt")
|
||||
public void testObjectExpression() throws Exception {
|
||||
doTest("compiler/testData/cfg/ObjectExpression.kt");
|
||||
@@ -121,6 +146,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
||||
doTest("compiler/testData/cfg/OnlyWhileInFunctionBody.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("propertySafeCall.kt")
|
||||
public void testPropertySafeCall() throws Exception {
|
||||
doTest("compiler/testData/cfg/propertySafeCall.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("ReturnFromExpression.kt")
|
||||
public void testReturnFromExpression() throws Exception {
|
||||
doTest("compiler/testData/cfg/ReturnFromExpression.kt");
|
||||
|
||||
Reference in New Issue
Block a user