Labels resolve removed from control flow graph
This commit is contained in:
@@ -1,10 +1,12 @@
|
|||||||
package org.jetbrains.jet.lang.cfg;
|
package org.jetbrains.jet.lang.cfg;
|
||||||
|
|
||||||
|
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.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.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
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;
|
||||||
@@ -20,7 +22,7 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
|||||||
*/
|
*/
|
||||||
public class JetControlFlowProcessor {
|
public class JetControlFlowProcessor {
|
||||||
|
|
||||||
private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
|
// private final Map<String, Stack<JetElement>> labeledElements = new HashMap<String, Stack<JetElement>>();
|
||||||
|
|
||||||
private final JetControlFlowBuilder builder;
|
private final JetControlFlowBuilder builder;
|
||||||
private final BindingTrace trace;
|
private final BindingTrace trace;
|
||||||
@@ -35,10 +37,10 @@ public class JetControlFlowProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List<? extends JetElement> body) {
|
public void generateSubroutineControlFlow(@NotNull JetElement subroutineElement, @NotNull List<? extends JetElement> body) {
|
||||||
if (subroutineElement instanceof JetNamedDeclaration) {
|
// if (subroutineElement instanceof JetNamedDeclaration) {
|
||||||
JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement;
|
// JetNamedDeclaration namedDeclaration = (JetNamedDeclaration) subroutineElement;
|
||||||
enterLabeledElement(JetPsiUtil.safeName(namedDeclaration.getName()), namedDeclaration);
|
// enterLabeledElement(JetPsiUtil.safeName(namedDeclaration.getName()), namedDeclaration);
|
||||||
}
|
// }
|
||||||
boolean functionLiteral = subroutineElement instanceof JetFunctionLiteralExpression;
|
boolean functionLiteral = subroutineElement instanceof JetFunctionLiteralExpression;
|
||||||
builder.enterSubroutine(subroutineElement, functionLiteral);
|
builder.enterSubroutine(subroutineElement, functionLiteral);
|
||||||
for (JetElement statement : body) {
|
for (JetElement statement : body) {
|
||||||
@@ -47,50 +49,50 @@ public class JetControlFlowProcessor {
|
|||||||
builder.exitSubroutine(subroutineElement, functionLiteral);
|
builder.exitSubroutine(subroutineElement, functionLiteral);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enterLabeledElement(@NotNull String labelName, @NotNull JetElement labeledElement) {
|
// private void enterLabeledElement(@NotNull String labelName, @NotNull JetElement labeledElement) {
|
||||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
// Stack<JetElement> stack = labeledElements.get(labelName);
|
||||||
if (stack == null) {
|
// if (stack == null) {
|
||||||
stack = new Stack<JetElement>();
|
// stack = new Stack<JetElement>();
|
||||||
labeledElements.put(labelName, stack);
|
// labeledElements.put(labelName, stack);
|
||||||
}
|
// }
|
||||||
stack.push(labeledElement);
|
// stack.push(labeledElement);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// private void exitElement(JetElement element) {
|
||||||
|
// // TODO : really suboptimal
|
||||||
|
// for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) {
|
||||||
|
// Map.Entry<String, Stack<JetElement>> entry = mapIter.next();
|
||||||
|
// Stack<JetElement> stack = entry.getValue();
|
||||||
|
// for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) {
|
||||||
|
// JetElement recorded = stackIter.next();
|
||||||
|
// if (recorded == element) {
|
||||||
|
// stackIter.remove();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (stack.isEmpty()) {
|
||||||
|
// mapIter.remove();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
private void exitElement(JetElement element) {
|
// @Nullable
|
||||||
// TODO : really suboptimal
|
// private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved) {
|
||||||
for (Iterator<Map.Entry<String, Stack<JetElement>>> mapIter = labeledElements.entrySet().iterator(); mapIter.hasNext(); ) {
|
// Stack<JetElement> stack = labeledElements.get(labelName);
|
||||||
Map.Entry<String, Stack<JetElement>> entry = mapIter.next();
|
// if (stack == null || stack.isEmpty()) {
|
||||||
Stack<JetElement> stack = entry.getValue();
|
// if (reportUnresolved) {
|
||||||
for (Iterator<JetElement> stackIter = stack.iterator(); stackIter.hasNext(); ) {
|
//// trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||||
JetElement recorded = stackIter.next();
|
// }
|
||||||
if (recorded == element) {
|
// return null;
|
||||||
stackIter.remove();
|
// }
|
||||||
}
|
// else if (stack.size() > 1) {
|
||||||
}
|
//// trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
|
||||||
if (stack.isEmpty()) {
|
//// trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||||
mapIter.remove();
|
// }
|
||||||
}
|
//
|
||||||
}
|
// JetElement result = stack.peek();
|
||||||
}
|
//// trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
||||||
|
// return result;
|
||||||
@Nullable
|
// }
|
||||||
private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved) {
|
|
||||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
|
||||||
if (stack == null || stack.isEmpty()) {
|
|
||||||
if (reportUnresolved) {
|
|
||||||
// trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
else if (stack.size() > 1) {
|
|
||||||
// trace.getErrorHandler().genericWarning(labelExpression.getNode(), "There is more than one label with such a name in this scope");
|
|
||||||
// trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
|
||||||
}
|
|
||||||
|
|
||||||
JetElement result = stack.peek();
|
|
||||||
// trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CFPVisitor extends JetVisitorVoid {
|
private class CFPVisitor extends JetVisitorVoid {
|
||||||
private final boolean inCondition;
|
private final boolean inCondition;
|
||||||
@@ -109,7 +111,7 @@ public class JetControlFlowProcessor {
|
|||||||
visitor = new CFPVisitor(inCondition);
|
visitor = new CFPVisitor(inCondition);
|
||||||
}
|
}
|
||||||
element.accept(visitor);
|
element.accept(visitor);
|
||||||
exitElement(element);
|
// exitElement(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -122,12 +124,12 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitThisExpression(JetThisExpression expression) {
|
public void visitThisExpression(JetThisExpression expression) {
|
||||||
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
// JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||||
if (targetLabel != null) {
|
// if (targetLabel != null) {
|
||||||
String labelName = expression.getLabelName();
|
// String labelName = expression.getLabelName();
|
||||||
assert labelName != null;
|
// assert labelName != null;
|
||||||
resolveLabel(labelName, targetLabel, false);
|
// resolveLabel(labelName, targetLabel, false);
|
||||||
}
|
// }
|
||||||
builder.read(expression);
|
builder.read(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +161,7 @@ public class JetControlFlowProcessor {
|
|||||||
private void visitLabeledExpression(@NotNull String labelName, @NotNull JetExpression labeledExpression) {
|
private void visitLabeledExpression(@NotNull String labelName, @NotNull JetExpression labeledExpression) {
|
||||||
JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression);
|
JetExpression deparenthesized = JetPsiUtil.deparenthesize(labeledExpression);
|
||||||
if (deparenthesized != null) {
|
if (deparenthesized != null) {
|
||||||
enterLabeledElement(labelName, deparenthesized);
|
// enterLabeledElement(labelName, deparenthesized);
|
||||||
value(labeledExpression, inCondition);
|
value(labeledExpression, inCondition);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -443,12 +445,20 @@ public class JetControlFlowProcessor {
|
|||||||
if (labelName != null) {
|
if (labelName != null) {
|
||||||
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
JetSimpleNameExpression targetLabel = expression.getTargetLabel();
|
||||||
assert targetLabel != null;
|
assert targetLabel != null;
|
||||||
loop = resolveLabel(labelName, targetLabel, true);
|
PsiElement labeledElement = BindingContextUtils.resolveToDeclarationPsiElement(trace.getBindingContext(), targetLabel);
|
||||||
if (!isLoop(loop)) {
|
if (labeledElement instanceof JetLoopExpression) {
|
||||||
// trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop");
|
loop = (JetLoopExpression) labeledElement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
|
trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
|
||||||
loop = null;
|
loop = null;
|
||||||
}
|
}
|
||||||
|
// loop = resolveLabel(labelName, targetLabel, true);
|
||||||
|
// if (!isLoop(loop)) {
|
||||||
|
//// trace.getErrorHandler().genericError(expression.getNode(), "The label '" + targetLabel.getText() + "' does not denote a loop");
|
||||||
|
// trace.report(NOT_A_LOOP_LABEL.on(expression, targetLabel.getText()));
|
||||||
|
// loop = null;
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
loop = builder.getCurrentLoop();
|
loop = builder.getCurrentLoop();
|
||||||
@@ -460,11 +470,11 @@ public class JetControlFlowProcessor {
|
|||||||
return loop;
|
return loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLoop(JetElement loop) {
|
// private boolean isLoop(JetElement loop) {
|
||||||
return loop instanceof JetWhileExpression ||
|
// return loop instanceof JetWhileExpression ||
|
||||||
loop instanceof JetDoWhileExpression ||
|
// loop instanceof JetDoWhileExpression ||
|
||||||
loop instanceof JetForExpression;
|
// loop instanceof JetForExpression;
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitReturnExpression(JetReturnExpression expression) {
|
public void visitReturnExpression(JetReturnExpression expression) {
|
||||||
@@ -477,7 +487,10 @@ public class JetControlFlowProcessor {
|
|||||||
if (labelElement != null) {
|
if (labelElement != null) {
|
||||||
String labelName = expression.getLabelName();
|
String labelName = expression.getLabelName();
|
||||||
assert labelName != null;
|
assert labelName != null;
|
||||||
subroutine = resolveLabel(labelName, labelElement, true);
|
PsiElement labeledElement = BindingContextUtils.resolveToDeclarationPsiElement(trace.getBindingContext(), labelElement);
|
||||||
|
assert labeledElement instanceof JetElement;
|
||||||
|
subroutine = (JetElement) labeledElement;
|
||||||
|
//subroutine = resolveLabel(labelName, labelElement, true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
subroutine = builder.getCurrentSubroutine();
|
subroutine = builder.getCurrentSubroutine();
|
||||||
|
|||||||
@@ -1343,11 +1343,11 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
else if (size == 0) {
|
else if (size == 0) {
|
||||||
//todo (first we put to the context, then get from it)
|
//todo (first we put to the context, then get from it)
|
||||||
labelsResolver.resolveLabel(labelName, targetLabel, false, context);
|
JetElement element = labelsResolver.resolveLabel(labelName, targetLabel, false, context);
|
||||||
// This uses the info written by the control flow processor
|
// This uses the info written by the control flow processor
|
||||||
PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(context.trace.getBindingContext(), targetLabel);
|
//PsiElement psiElement = BindingContextUtils.resolveToDeclarationPsiElement(context.trace.getBindingContext(), targetLabel);
|
||||||
if (psiElement instanceof JetFunctionLiteralExpression) {
|
if (element instanceof JetFunctionLiteralExpression) {
|
||||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
|
||||||
if (declarationDescriptor instanceof FunctionDescriptor) {
|
if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||||
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver();
|
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver();
|
||||||
if (thisReceiver.exists()) {
|
if (thisReceiver.exists()) {
|
||||||
@@ -2911,7 +2911,7 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved, TypeInferenceContext context) {
|
private JetElement resolveLabel(@NotNull String labelName, @NotNull JetSimpleNameExpression labelExpression, boolean reportUnresolved, TypeInferenceContext context) {
|
||||||
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
|
Collection<DeclarationDescriptor> declarationsByLabel = context.scope.getDeclarationsByLabel(labelName);
|
||||||
int size = declarationsByLabel.size();
|
int size = declarationsByLabel.size();
|
||||||
|
|
||||||
@@ -2930,7 +2930,7 @@ public class JetTypeInferrer {
|
|||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
context.trace.record(LABEL_TARGET, labelExpression, element);
|
context.trace.record(LABEL_TARGET, labelExpression, element);
|
||||||
return;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stack<JetElement> stack = labeledElements.get(labelName);
|
Stack<JetElement> stack = labeledElements.get(labelName);
|
||||||
@@ -2938,7 +2938,7 @@ public class JetTypeInferrer {
|
|||||||
if (reportUnresolved) {
|
if (reportUnresolved) {
|
||||||
context.trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
context.trace.report(UNRESOLVED_REFERENCE.on(labelExpression));
|
||||||
}
|
}
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
else if (stack.size() > 1) {
|
else if (stack.size() > 1) {
|
||||||
context.trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
context.trace.report(LABEL_NAME_CLASH.on(labelExpression));
|
||||||
@@ -2946,6 +2946,7 @@ public class JetTypeInferrer {
|
|||||||
|
|
||||||
JetElement result = stack.peek();
|
JetElement result = stack.peek();
|
||||||
context.trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
context.trace.record(BindingContext.LABEL_TARGET, labelExpression, result);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void resolveCorrespondingLoopLabel(JetLabelQualifiedExpression expression, TypeInferenceContext context) {
|
private void resolveCorrespondingLoopLabel(JetLabelQualifiedExpression expression, TypeInferenceContext context) {
|
||||||
|
|||||||
Reference in New Issue
Block a user