responsibility of computing data flow moved to JetFlowInformationProvider
This commit is contained in:
@@ -2,7 +2,6 @@ package org.jetbrains.jet.lang;
|
|||||||
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||||
import org.jetbrains.jet.lang.resolve.*;
|
import org.jetbrains.jet.lang.resolve.*;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
@@ -19,18 +18,12 @@ public class JetSemanticServices {
|
|||||||
return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), JetControlFlowDataTraceFactory.EMPTY);
|
return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), JetControlFlowDataTraceFactory.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JetSemanticServices createSemanticServices(Project project, JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
|
||||||
return new JetSemanticServices(JetStandardLibrary.getJetStandardLibrary(project), flowDataTraceFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final JetStandardLibrary standardLibrary;
|
private final JetStandardLibrary standardLibrary;
|
||||||
private final JetTypeChecker typeChecker;
|
private final JetTypeChecker typeChecker;
|
||||||
private final JetControlFlowDataTraceFactory flowDataTraceFactory;
|
|
||||||
|
|
||||||
private JetSemanticServices(JetStandardLibrary standardLibrary, JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
private JetSemanticServices(JetStandardLibrary standardLibrary, JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||||
this.standardLibrary = standardLibrary;
|
this.standardLibrary = standardLibrary;
|
||||||
this.typeChecker = new JetTypeChecker(standardLibrary);
|
this.typeChecker = new JetTypeChecker(standardLibrary);
|
||||||
this.flowDataTraceFactory = flowDataTraceFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -40,7 +33,7 @@ public class JetSemanticServices {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) {
|
public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) {
|
||||||
return new ClassDescriptorResolver(this, trace, flowDataTraceFactory);
|
return new ClassDescriptorResolver(this, trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -1,92 +1,236 @@
|
|||||||
package org.jetbrains.jet.lang.cfg;
|
package org.jetbrains.jet.lang.cfg;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.lang.cfg.pseudocode.*;
|
||||||
import org.jetbrains.jet.lang.psi.JetElement;
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetLoopExpression;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author svtk
|
||||||
*/
|
*/
|
||||||
public interface JetFlowInformationProvider {
|
public class JetFlowInformationProvider {
|
||||||
// JetFlowInformationProvider THROW_EXCEPTION = new JetFlowInformationProvider() {
|
|
||||||
// @Override
|
private final Map<JetElement, Pseudocode> pseudocodeMap;
|
||||||
|
|
||||||
|
public JetFlowInformationProvider(@NotNull JetElement declaration, @NotNull final JetExpression bodyExpression, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory, @NotNull BindingTrace trace) {
|
||||||
|
final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration);
|
||||||
|
pseudocodeMap = new HashMap<JetElement, Pseudocode>();
|
||||||
|
final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>();
|
||||||
|
final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
|
||||||
|
JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() {
|
||||||
|
@Override
|
||||||
|
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
|
||||||
|
pseudocodeTrace.recordControlFlowData(element, pseudocode);
|
||||||
|
pseudocodeMap.put(element, pseudocode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
|
||||||
|
Instruction oldValue = representativeInstructions.put(element, instruction);
|
||||||
|
// assert oldValue == null : element.getText();
|
||||||
|
pseudocodeTrace.recordRepresentativeInstruction(element, instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
|
||||||
|
loopInfo.put(expression, blockInfo);
|
||||||
|
pseudocodeTrace.recordLoopInfo(expression, blockInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
pseudocodeTrace.close();
|
||||||
|
for (Pseudocode pseudocode : pseudocodeMap.values()) {
|
||||||
|
pseudocode.postProcess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(wrappedTrace);
|
||||||
|
new JetControlFlowProcessor(trace, instructionsGenerator).generate(declaration, bodyExpression);
|
||||||
|
wrappedTrace.close();
|
||||||
|
}
|
||||||
|
|
||||||
// public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
|
// public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
|
||||||
// throw new UnsupportedOperationException();
|
// Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||||
// }
|
// assert pseudocode != null;
|
||||||
//
|
//
|
||||||
// @Override
|
// SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
|
||||||
// public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions) {
|
// processPreviousInstructions(exitInstruction, new HashSet<Instruction>(), returnedExpressions, elementsReturningUnit);
|
||||||
// throw new UnsupportedOperationException();
|
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
// @Override
|
public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection<JetExpression> returnedExpressions) {
|
||||||
// public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
|
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||||
// throw new UnsupportedOperationException();
|
assert pseudocode != null;
|
||||||
// }
|
|
||||||
//
|
SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
|
||||||
// @Override
|
for (Instruction previousInstruction : exitInstruction.getPreviousInstructions()) {
|
||||||
|
previousInstruction.accept(new InstructionVisitor() {
|
||||||
|
@Override
|
||||||
|
public void visitReturnValue(ReturnValueInstruction instruction) {
|
||||||
|
returnedExpressions.add((JetExpression) instruction.getElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitReturnNoValue(ReturnNoValueInstruction instruction) {
|
||||||
|
returnedExpressions.add((JetExpression) instruction.getElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJump(AbstractJumpInstruction instruction) {
|
||||||
|
// Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitInstruction(Instruction instruction) {
|
||||||
|
if (instruction instanceof JetElementInstruction) {
|
||||||
|
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
|
||||||
|
returnedExpressions.add((JetExpression) elementInstruction.getElement());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new IllegalStateException(instruction + " precedes the exit point");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
|
||||||
|
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||||
|
assert pseudocode != null;
|
||||||
|
|
||||||
|
SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
|
||||||
|
Set<Instruction> visited = new HashSet<Instruction>();
|
||||||
|
collectReachable(enterInstruction, visited, null);
|
||||||
|
|
||||||
|
for (Instruction instruction : pseudocode.getInstructions()) {
|
||||||
|
if (!visited.contains(instruction) &&
|
||||||
|
instruction instanceof JetElementInstruction &&
|
||||||
|
// TODO : do {return} while (1 > a)
|
||||||
|
!(instruction instanceof ReadUnitValueInstruction)) {
|
||||||
|
unreachableElements.add(((JetElementInstruction) instruction).getElement());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
// public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
||||||
// throw new UnsupportedOperationException();
|
// Instruction dominatorInstruction = representativeInstructions.get(dominator);
|
||||||
|
// if (dominatorInstruction == null) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// SubroutineEnterInstruction enterInstruction = dominatorInstruction.getOwner().getEnterInstruction();
|
||||||
|
//
|
||||||
|
// Set<Instruction> reachable = new HashSet<Instruction>();
|
||||||
|
// collectReachable(enterInstruction, reachable, null);
|
||||||
|
//
|
||||||
|
// Set<Instruction> reachableWithDominatorProhibited = new HashSet<Instruction>();
|
||||||
|
// reachableWithDominatorProhibited.add(dominatorInstruction);
|
||||||
|
// collectReachable(enterInstruction, reachableWithDominatorProhibited, null);
|
||||||
|
//
|
||||||
|
// for (Instruction instruction : reachable) {
|
||||||
|
// if (instruction instanceof JetElementInstruction
|
||||||
|
// && reachable.contains(instruction)
|
||||||
|
// && !reachableWithDominatorProhibited.contains(instruction)) {
|
||||||
|
// JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
|
||||||
|
// dominated.add(elementInstruction.getElement());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// @Override
|
|
||||||
// public boolean isBreakable(JetLoopExpression loop) {
|
// public boolean isBreakable(JetLoopExpression loop) {
|
||||||
// throw new UnsupportedOperationException();
|
// LoopInfo info = loopInfo.get(loop);
|
||||||
|
// Pseudocode.PseudocodeLabel bodyEntryPoint = (Pseudocode.PseudocodeLabel) info.getBodyEntryPoint();
|
||||||
|
// Pseudocode.PseudocodeLabel exitPoint = (Pseudocode.PseudocodeLabel) info.getExitPoint();
|
||||||
|
// HashSet<Instruction> visited = Sets.newHashSet();
|
||||||
|
// Pseudocode.PseudocodeLabel conditionEntryPoint = (Pseudocode.PseudocodeLabel) info.getConditionEntryPoint();
|
||||||
|
// visited.add(conditionEntryPoint.resolveToInstruction());
|
||||||
|
// return collectReachable(bodyEntryPoint.resolveToInstruction(), visited, exitPoint.resolveToInstruction());
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// };
|
// public boolean isReachable(JetExpression from, JetExpression to) {
|
||||||
//
|
// Instruction fromInstr = representativeInstructions.get(from);
|
||||||
// JetFlowInformationProvider NONE = new JetFlowInformationProvider() {
|
// assert fromInstr != null : "No representative instruction for " + from.getText();
|
||||||
// @Override
|
// Instruction toInstr = representativeInstructions.get(to);
|
||||||
// public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
|
// assert toInstr != null : "No representative instruction for " + to.getText();
|
||||||
//
|
//
|
||||||
|
// return collectReachable(fromInstr, Sets.<Instruction>newHashSet(), toInstr);
|
||||||
// }
|
// }
|
||||||
//
|
// }
|
||||||
// @Override
|
|
||||||
// public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Override
|
|
||||||
// public boolean isBreakable(JetLoopExpression loop) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// };
|
|
||||||
|
|
||||||
/**
|
private boolean collectReachable(Instruction current, Set<Instruction> visited, @Nullable Instruction lookFor) {
|
||||||
* Collects expressions returned from the given subroutine and 'return;' expressions
|
if (!visited.add(current)) return false;
|
||||||
*/
|
if (current == lookFor) return true;
|
||||||
void collectReturnedInformation(
|
|
||||||
@NotNull JetElement subroutine,
|
|
||||||
@NotNull Collection<JetExpression> returnedExpressions,
|
|
||||||
@NotNull Collection<JetElement> elementsReturningUnit);
|
|
||||||
|
|
||||||
/**
|
for (Instruction nextInstruction : current.getNextInstructions()) {
|
||||||
* Collects all 'return ...' expressions that return from the given subroutine and all the expressions that precede the exit point
|
if (collectReachable(nextInstruction, visited, lookFor)) {
|
||||||
*/
|
return true;
|
||||||
void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions);
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void collectUnreachableExpressions(
|
// private void processPreviousInstructions(Instruction previousFor, final Set<Instruction> visited, final Collection<JetExpression> returnedExpressions, final Collection<JetElement> elementsReturningUnit) {
|
||||||
@NotNull JetElement subroutine,
|
// if (!visited.add(previousFor)) return;
|
||||||
@NotNull Collection<JetElement> unreachableElements);
|
//
|
||||||
|
// Collection<Instruction> previousInstructions = previousFor.getPreviousInstructions();
|
||||||
void collectDominatedExpressions(
|
// InstructionVisitor visitor = new InstructionVisitor() {
|
||||||
@NotNull JetExpression dominator,
|
// @Override
|
||||||
@NotNull Collection<JetElement> dominated);
|
// public void visitReadValue(ReadValueInstruction instruction) {
|
||||||
|
// returnedExpressions.add((JetExpression) instruction.getElement());
|
||||||
boolean isBreakable(JetLoopExpression loop);
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void visitReturnValue(ReturnValueInstruction instruction) {
|
||||||
|
// processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void visitReturnNoValue(ReturnNoValueInstruction instruction) {
|
||||||
|
// elementsReturningUnit.add(instruction.getElement());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void visitSubroutineEnter(SubroutineEnterInstruction instruction) {
|
||||||
|
// elementsReturningUnit.add(instruction.getSubroutine());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void visitUnsupportedElementInstruction(UnsupportedElementInstruction instruction) {
|
||||||
|
// context.getTrace().report(UNSUPPORTED.on(instruction.getElement(), "Control-flow builder"));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void visitWriteValue(WriteValueInstruction writeValueInstruction) {
|
||||||
|
// elementsReturningUnit.add(writeValueInstruction.getElement());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void visitJump(AbstractJumpInstruction instruction) {
|
||||||
|
// processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void visitReadUnitValue(ReadUnitValueInstruction instruction) {
|
||||||
|
// returnedExpressions.add((JetExpression) instruction.getElement());
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @Override
|
||||||
|
// public void visitInstruction(Instruction instruction) {
|
||||||
|
// if (instruction instanceof JetElementInstructionImpl) {
|
||||||
|
// JetElementInstructionImpl elementInstruction = (JetElementInstructionImpl) instruction;
|
||||||
|
// context.getTrace().report(UNSUPPORTED.on(elementInstruction.getElement(), "Control-flow builder"));
|
||||||
|
// }
|
||||||
|
// else {
|
||||||
|
// throw new UnsupportedOperationException(instruction.toString());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// for (Instruction previousInstruction : previousInstructions) {
|
||||||
|
// previousInstruction.accept(visitor);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class AnalyzingUtils {
|
|||||||
|
|
||||||
public BindingContext analyzeNamespaces(@NotNull Project project, @NotNull List<? extends JetDeclaration> declarations, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
public BindingContext analyzeNamespaces(@NotNull Project project, @NotNull List<? extends JetDeclaration> declarations, @NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||||
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project, flowDataTraceFactory);
|
JetSemanticServices semanticServices = JetSemanticServices.createSemanticServices(project);
|
||||||
|
|
||||||
JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope();
|
JetScope libraryScope = semanticServices.getStandardLibrary().getLibraryScope();
|
||||||
ModuleDescriptor owner = new ModuleDescriptor("<module>");
|
ModuleDescriptor owner = new ModuleDescriptor("<module>");
|
||||||
@@ -111,7 +111,7 @@ public class AnalyzingUtils {
|
|||||||
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
||||||
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
|
throw new IllegalStateException("Must be guaranteed not to happen by the parser");
|
||||||
}
|
}
|
||||||
}, declarations);
|
}, declarations, flowDataTraceFactory);
|
||||||
return bindingTraceContext.getBindingContext();
|
return bindingTraceContext.getBindingContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import com.google.common.collect.Lists;
|
|||||||
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.JetSemanticServices;
|
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetAnnotationEntry;
|
import org.jetbrains.jet.lang.psi.JetAnnotationEntry;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import com.intellij.lang.ASTNode;
|
|||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.intellij.util.containers.Queue;
|
import com.intellij.util.containers.Queue;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
|
|||||||
@@ -2,17 +2,12 @@ package org.jetbrains.jet.lang.resolve;
|
|||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
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.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||||
import org.jetbrains.jet.lang.cfg.JetControlFlowProcessor;
|
|
||||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
|
||||||
import org.jetbrains.jet.lang.cfg.LoopInfo;
|
|
||||||
import org.jetbrains.jet.lang.cfg.pseudocode.*;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
@@ -35,15 +30,13 @@ public class ClassDescriptorResolver {
|
|||||||
private final TypeResolver typeResolver;
|
private final TypeResolver typeResolver;
|
||||||
private final TypeResolver typeResolverNotCheckingBounds;
|
private final TypeResolver typeResolverNotCheckingBounds;
|
||||||
private final BindingTrace trace;
|
private final BindingTrace trace;
|
||||||
private final JetControlFlowDataTraceFactory flowDataTraceFactory;
|
|
||||||
private final AnnotationResolver annotationResolver;
|
private final AnnotationResolver annotationResolver;
|
||||||
|
|
||||||
public ClassDescriptorResolver(JetSemanticServices semanticServices, BindingTrace trace, JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
public ClassDescriptorResolver(JetSemanticServices semanticServices, BindingTrace trace) {
|
||||||
this.semanticServices = semanticServices;
|
this.semanticServices = semanticServices;
|
||||||
this.typeResolver = new TypeResolver(semanticServices, trace, true);
|
this.typeResolver = new TypeResolver(semanticServices, trace, true);
|
||||||
this.typeResolverNotCheckingBounds = new TypeResolver(semanticServices, trace, false);
|
this.typeResolverNotCheckingBounds = new TypeResolver(semanticServices, trace, false);
|
||||||
this.trace = trace;
|
this.trace = trace;
|
||||||
this.flowDataTraceFactory = flowDataTraceFactory;
|
|
||||||
this.annotationResolver = new AnnotationResolver(semanticServices, trace);
|
this.annotationResolver = new AnnotationResolver(semanticServices, trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -813,230 +806,4 @@ public class ClassDescriptorResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public JetFlowInformationProvider computeFlowData(@NotNull JetElement declaration, @NotNull final JetExpression bodyExpression) {
|
|
||||||
final JetPseudocodeTrace pseudocodeTrace = flowDataTraceFactory.createTrace(declaration);
|
|
||||||
final Map<JetElement, Pseudocode> pseudocodeMap = new HashMap<JetElement, Pseudocode>();
|
|
||||||
final Map<JetElement, Instruction> representativeInstructions = new HashMap<JetElement, Instruction>();
|
|
||||||
final Map<JetExpression, LoopInfo> loopInfo = Maps.newHashMap();
|
|
||||||
JetPseudocodeTrace wrappedTrace = new JetPseudocodeTrace() {
|
|
||||||
@Override
|
|
||||||
public void recordControlFlowData(@NotNull JetElement element, @NotNull Pseudocode pseudocode) {
|
|
||||||
pseudocodeTrace.recordControlFlowData(element, pseudocode);
|
|
||||||
pseudocodeMap.put(element, pseudocode);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recordRepresentativeInstruction(@NotNull JetElement element, @NotNull Instruction instruction) {
|
|
||||||
Instruction oldValue = representativeInstructions.put(element, instruction);
|
|
||||||
// assert oldValue == null : element.getText();
|
|
||||||
pseudocodeTrace.recordRepresentativeInstruction(element, instruction);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void recordLoopInfo(JetExpression expression, LoopInfo blockInfo) {
|
|
||||||
loopInfo.put(expression, blockInfo);
|
|
||||||
pseudocodeTrace.recordLoopInfo(expression, blockInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
pseudocodeTrace.close();
|
|
||||||
for (Pseudocode pseudocode : pseudocodeMap.values()) {
|
|
||||||
pseudocode.postProcess();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
JetControlFlowInstructionsGenerator instructionsGenerator = new JetControlFlowInstructionsGenerator(wrappedTrace);
|
|
||||||
new JetControlFlowProcessor(trace, instructionsGenerator).generate(declaration, bodyExpression);
|
|
||||||
wrappedTrace.close();
|
|
||||||
return new JetFlowInformationProvider() {
|
|
||||||
@Override
|
|
||||||
public void collectReturnedInformation(@NotNull JetElement subroutine, @NotNull Collection<JetExpression> returnedExpressions, @NotNull Collection<JetElement> elementsReturningUnit) {
|
|
||||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
|
||||||
assert pseudocode != null;
|
|
||||||
|
|
||||||
SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
|
|
||||||
processPreviousInstructions(exitInstruction, new HashSet<Instruction>(), returnedExpressions, elementsReturningUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void collectReturnExpressions(@NotNull JetElement subroutine, @NotNull final Collection<JetExpression> returnedExpressions) {
|
|
||||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
|
||||||
assert pseudocode != null;
|
|
||||||
|
|
||||||
SubroutineExitInstruction exitInstruction = pseudocode.getExitInstruction();
|
|
||||||
for (Instruction previousInstruction : exitInstruction.getPreviousInstructions()) {
|
|
||||||
previousInstruction.accept(new InstructionVisitor() {
|
|
||||||
@Override
|
|
||||||
public void visitReturnValue(ReturnValueInstruction instruction) {
|
|
||||||
returnedExpressions.add((JetExpression) instruction.getElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitReturnNoValue(ReturnNoValueInstruction instruction) {
|
|
||||||
returnedExpressions.add((JetExpression) instruction.getElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitJump(AbstractJumpInstruction instruction) {
|
|
||||||
// Nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitInstruction(Instruction instruction) {
|
|
||||||
if (instruction instanceof JetElementInstruction) {
|
|
||||||
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
|
|
||||||
returnedExpressions.add((JetExpression) elementInstruction.getElement());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new IllegalStateException(instruction + " precedes the exit point");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void collectUnreachableExpressions(@NotNull JetElement subroutine, @NotNull Collection<JetElement> unreachableElements) {
|
|
||||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
|
||||||
assert pseudocode != null;
|
|
||||||
|
|
||||||
SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
|
|
||||||
Set<Instruction> visited = new HashSet<Instruction>();
|
|
||||||
collectReachable(enterInstruction, visited, null);
|
|
||||||
|
|
||||||
for (Instruction instruction : pseudocode.getInstructions()) {
|
|
||||||
if (!visited.contains(instruction) &&
|
|
||||||
instruction instanceof JetElementInstruction &&
|
|
||||||
// TODO : do {return} while (1 > a)
|
|
||||||
!(instruction instanceof ReadUnitValueInstruction)) {
|
|
||||||
unreachableElements.add(((JetElementInstruction) instruction).getElement());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void collectDominatedExpressions(@NotNull JetExpression dominator, @NotNull Collection<JetElement> dominated) {
|
|
||||||
Instruction dominatorInstruction = representativeInstructions.get(dominator);
|
|
||||||
if (dominatorInstruction == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SubroutineEnterInstruction enterInstruction = dominatorInstruction.getOwner().getEnterInstruction();
|
|
||||||
|
|
||||||
Set<Instruction> reachable = new HashSet<Instruction>();
|
|
||||||
collectReachable(enterInstruction, reachable, null);
|
|
||||||
|
|
||||||
Set<Instruction> reachableWithDominatorProhibited = new HashSet<Instruction>();
|
|
||||||
reachableWithDominatorProhibited.add(dominatorInstruction);
|
|
||||||
collectReachable(enterInstruction, reachableWithDominatorProhibited, null);
|
|
||||||
|
|
||||||
for (Instruction instruction : reachable) {
|
|
||||||
if (instruction instanceof JetElementInstruction
|
|
||||||
&& reachable.contains(instruction)
|
|
||||||
&& !reachableWithDominatorProhibited.contains(instruction)) {
|
|
||||||
JetElementInstruction elementInstruction = (JetElementInstruction) instruction;
|
|
||||||
dominated.add(elementInstruction.getElement());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isBreakable(JetLoopExpression loop) {
|
|
||||||
LoopInfo info = loopInfo.get(loop);
|
|
||||||
Pseudocode.PseudocodeLabel bodyEntryPoint = (Pseudocode.PseudocodeLabel) info.getBodyEntryPoint();
|
|
||||||
Pseudocode.PseudocodeLabel exitPoint = (Pseudocode.PseudocodeLabel) info.getExitPoint();
|
|
||||||
HashSet<Instruction> visited = Sets.newHashSet();
|
|
||||||
Pseudocode.PseudocodeLabel conditionEntryPoint = (Pseudocode.PseudocodeLabel) info.getConditionEntryPoint();
|
|
||||||
visited.add(conditionEntryPoint.resolveToInstruction());
|
|
||||||
return collectReachable(bodyEntryPoint.resolveToInstruction(), visited, exitPoint.resolveToInstruction());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isReachable(JetExpression from, JetExpression to) {
|
|
||||||
Instruction fromInstr = representativeInstructions.get(from);
|
|
||||||
assert fromInstr != null : "No representative instruction for " + from.getText();
|
|
||||||
Instruction toInstr = representativeInstructions.get(to);
|
|
||||||
assert toInstr != null : "No representative instruction for " + to.getText();
|
|
||||||
|
|
||||||
return collectReachable(fromInstr, Sets.<Instruction>newHashSet(), toInstr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean collectReachable(Instruction current, Set<Instruction> visited, @Nullable Instruction lookFor) {
|
|
||||||
if (!visited.add(current)) return false;
|
|
||||||
if (current == lookFor) return true;
|
|
||||||
|
|
||||||
for (Instruction nextInstruction : current.getNextInstructions()) {
|
|
||||||
if (collectReachable(nextInstruction, visited, lookFor)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void processPreviousInstructions(Instruction previousFor, final Set<Instruction> visited, final Collection<JetExpression> returnedExpressions, final Collection<JetElement> elementsReturningUnit) {
|
|
||||||
if (!visited.add(previousFor)) return;
|
|
||||||
|
|
||||||
Collection<Instruction> previousInstructions = previousFor.getPreviousInstructions();
|
|
||||||
InstructionVisitor visitor = new InstructionVisitor() {
|
|
||||||
@Override
|
|
||||||
public void visitReadValue(ReadValueInstruction instruction) {
|
|
||||||
returnedExpressions.add((JetExpression) instruction.getElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitReturnValue(ReturnValueInstruction instruction) {
|
|
||||||
processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitReturnNoValue(ReturnNoValueInstruction instruction) {
|
|
||||||
elementsReturningUnit.add(instruction.getElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitSubroutineEnter(SubroutineEnterInstruction instruction) {
|
|
||||||
elementsReturningUnit.add(instruction.getSubroutine());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitUnsupportedElementInstruction(UnsupportedElementInstruction instruction) {
|
|
||||||
// trace.getErrorHandler().genericError(instruction.getElement().getNode(), "Unsupported by control-flow builder " + instruction.getElement());
|
|
||||||
trace.report(UNSUPPORTED.on(instruction.getElement(), "Control-flow builder"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitWriteValue(WriteValueInstruction writeValueInstruction) {
|
|
||||||
elementsReturningUnit.add(writeValueInstruction.getElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitJump(AbstractJumpInstruction instruction) {
|
|
||||||
processPreviousInstructions(instruction, visited, returnedExpressions, elementsReturningUnit);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitReadUnitValue(ReadUnitValueInstruction instruction) {
|
|
||||||
returnedExpressions.add((JetExpression) instruction.getElement());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitInstruction(Instruction instruction) {
|
|
||||||
if (instruction instanceof JetElementInstructionImpl) {
|
|
||||||
JetElementInstructionImpl elementInstruction = (JetElementInstructionImpl) instruction;
|
|
||||||
// trace.getErrorHandler().genericError(elementInstruction.getElement().getNode(), "Unsupported by control-flow builder " + elementInstruction.getElement());
|
|
||||||
trace.report(UNSUPPORTED.on(elementInstruction.getElement(), "Control-flow builder"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new UnsupportedOperationException(instruction.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
for (Instruction previousInstruction : previousInstructions) {
|
|
||||||
previousInstruction.accept(visitor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.jetbrains.jet.lang.resolve;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
|
||||||
|
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||||
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptorImpl;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptorImpl;
|
||||||
@@ -12,7 +13,6 @@ 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.JetTypeInferrer;
|
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -25,11 +25,13 @@ import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
|||||||
*/
|
*/
|
||||||
public class ControlFlowAnalyzer {
|
public class ControlFlowAnalyzer {
|
||||||
private TopDownAnalysisContext context;
|
private TopDownAnalysisContext context;
|
||||||
private JetTypeInferrer.Services typeInferrer;
|
private JetTypeInferrer.Services typeInferrerServices;
|
||||||
|
private final JetControlFlowDataTraceFactory flowDataTraceFactory;
|
||||||
|
|
||||||
public ControlFlowAnalyzer(TopDownAnalysisContext context) {
|
public ControlFlowAnalyzer(TopDownAnalysisContext context, JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
typeInferrer = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
|
this.flowDataTraceFactory = flowDataTraceFactory;
|
||||||
|
this.typeInferrerServices = context.getSemanticServices().getTypeInferrerServices(context.getTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void process() {
|
public void process() {
|
||||||
@@ -37,7 +39,9 @@ public class ControlFlowAnalyzer {
|
|||||||
JetNamedFunction function = entry.getKey();
|
JetNamedFunction function = entry.getKey();
|
||||||
FunctionDescriptorImpl functionDescriptor = entry.getValue();
|
FunctionDescriptorImpl functionDescriptor = entry.getValue();
|
||||||
|
|
||||||
final JetType expectedReturnType = !function.hasBlockBody() && !function.hasDeclaredReturnType() ? NO_EXPECTED_TYPE : functionDescriptor.getReturnType();
|
final JetType expectedReturnType = !function.hasBlockBody() && !function.hasDeclaredReturnType()
|
||||||
|
? NO_EXPECTED_TYPE
|
||||||
|
: functionDescriptor.getReturnType();
|
||||||
checkFunction(function, functionDescriptor, expectedReturnType);
|
checkFunction(function, functionDescriptor, expectedReturnType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +62,7 @@ public class ControlFlowAnalyzer {
|
|||||||
private void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, final @NotNull JetType expectedReturnType) {
|
private void checkFunction(JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, final @NotNull JetType expectedReturnType) {
|
||||||
JetExpression bodyExpression = function.getBodyExpression();
|
JetExpression bodyExpression = function.getBodyExpression();
|
||||||
if (bodyExpression == null) return;
|
if (bodyExpression == null) return;
|
||||||
JetFlowInformationProvider flowInformationProvider = context.getClassDescriptorResolver().computeFlowData((JetElement) function, bodyExpression);
|
JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetElement) function, bodyExpression, flowDataTraceFactory, context.getTrace());
|
||||||
|
|
||||||
final boolean blockBody = function.hasBlockBody();
|
final boolean blockBody = function.hasBlockBody();
|
||||||
List<JetElement> unreachableElements = Lists.newArrayList();
|
List<JetElement> unreachableElements = Lists.newArrayList();
|
||||||
@@ -96,7 +100,7 @@ public class ControlFlowAnalyzer {
|
|||||||
@Override
|
@Override
|
||||||
public void visitExpression(JetExpression expression) {
|
public void visitExpression(JetExpression expression) {
|
||||||
if (blockBody && expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) {
|
if (blockBody && expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) {
|
||||||
JetType type = typeInferrer.getType(scope, expression, expectedReturnType);
|
JetType type = typeInferrerServices.getType(scope, expression, expectedReturnType);
|
||||||
if (type == null || !JetStandardClasses.isNothing(type)) {
|
if (type == null || !JetStandardClasses.isNothing(type)) {
|
||||||
context.getTrace().report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(expression));
|
context.getTrace().report(NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY.on(expression));
|
||||||
}
|
}
|
||||||
@@ -109,6 +113,6 @@ public class ControlFlowAnalyzer {
|
|||||||
private void checkProperty(JetProperty property) {
|
private void checkProperty(JetProperty property) {
|
||||||
JetExpression initializer = property.getInitializer();
|
JetExpression initializer = property.getInitializer();
|
||||||
if (initializer == null) return;
|
if (initializer == null) return;
|
||||||
context.getClassDescriptorResolver().computeFlowData(property, initializer);
|
new JetFlowInformationProvider(property, initializer, flowDataTraceFactory, context.getTrace());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package org.jetbrains.jet.lang.resolve;
|
package org.jetbrains.jet.lang.resolve;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||||
|
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
@@ -55,13 +55,16 @@ public class TopDownAnalyzer {
|
|||||||
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptor classObjectDescriptor) {
|
||||||
return ClassObjectStatus.NOT_ALLOWED;
|
return ClassObjectStatus.NOT_ALLOWED;
|
||||||
}
|
}
|
||||||
}, Collections.<JetDeclaration>singletonList(object));
|
}, Collections.<JetDeclaration>singletonList(object), JetControlFlowDataTraceFactory.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void process(
|
public static void process(
|
||||||
@NotNull JetSemanticServices semanticServices,
|
@NotNull JetSemanticServices semanticServices,
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull JetScope outerScope, NamespaceLike owner, @NotNull List<? extends JetDeclaration> declarations) {
|
@NotNull JetScope outerScope,
|
||||||
|
NamespaceLike owner,
|
||||||
|
@NotNull List<? extends JetDeclaration> declarations,
|
||||||
|
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||||
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace);
|
TopDownAnalysisContext context = new TopDownAnalysisContext(semanticServices, trace);
|
||||||
new TypeHierarchyResolver(context).process(outerScope, owner, declarations);
|
new TypeHierarchyResolver(context).process(outerScope, owner, declarations);
|
||||||
new DeclarationResolver(context).process();
|
new DeclarationResolver(context).process();
|
||||||
@@ -69,7 +72,7 @@ public class TopDownAnalyzer {
|
|||||||
new OverrideResolver(context).process();
|
new OverrideResolver(context).process();
|
||||||
new BodyResolver(context).resolveBehaviorDeclarationBodies();
|
new BodyResolver(context).resolveBehaviorDeclarationBodies();
|
||||||
new DeclarationsChecker(context).process();
|
new DeclarationsChecker(context).process();
|
||||||
new ControlFlowAnalyzer(context).process();
|
new ControlFlowAnalyzer(context, flowDataTraceFactory).process();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void processStandardLibraryNamespace(
|
public static void processStandardLibraryNamespace(
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.psi.PsiNameIdentifierOwner;
|
import com.intellij.psi.PsiNameIdentifierOwner;
|
||||||
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.cfg.JetFlowInformationProvider;
|
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -21,9 +20,7 @@ import org.jetbrains.jet.lexer.JetTokens;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.CONSTRUCTOR;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.DESCRIPTOR_TO_DECLARATION;
|
|
||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
|
|||||||
Reference in New Issue
Block a user