no need in possible local initializers

for each variable for each instruction
rename
This commit is contained in:
Svetlana Isakova
2012-05-28 13:48:49 +04:00
parent 468052c3a5
commit de67cae571
3 changed files with 120 additions and 151 deletions
@@ -25,8 +25,8 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.*;
import org.jetbrains.jet.lang.cfg.PseudocodeTraverser.*;
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitializers;
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseStatus;
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableInitState;
import org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
@@ -41,6 +41,7 @@ import org.jetbrains.jet.plugin.JetMainDetector;
import java.util.*;
import static org.jetbrains.jet.lang.cfg.PseudocodeVariablesData.VariableUseState.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
import static org.jetbrains.jet.lang.resolve.BindingContext.CAPTURED_IN_CLOSURE;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
@@ -187,38 +188,38 @@ public class JetFlowInformationProvider {
final Collection<VariableDescriptor> varWithValReassignErrorGenerated = Sets.newHashSet();
final boolean processClassOrObject = subroutine instanceof JetClassOrObject;
Map<Instruction, Edges<Map<VariableDescriptor,VariableInitializers>>> initializers = pseudocodeVariablesData.getVariableInitializers();
Map<Instruction, Edges<Map<VariableDescriptor,VariableInitState>>> initializers = pseudocodeVariablesData.getVariableInitializers();
final Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode);
PseudocodeTraverser.traverse(pseudocode, true, true, initializers, new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableInitializers>>() {
PseudocodeTraverser.traverse(pseudocode, true, true, initializers, new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState>>() {
@Override
public void execute(@NotNull Instruction instruction,
@Nullable Map<VariableDescriptor, VariableInitializers> in,
@Nullable Map<VariableDescriptor, VariableInitializers> out) {
@Nullable Map<VariableDescriptor, VariableInitState> in,
@Nullable Map<VariableDescriptor, PseudocodeVariablesData.VariableInitState> out) {
assert in != null && out != null;
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true, trace.getBindingContext());
if (variableDescriptor == null) return;
if (!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction)) return;
VariableInitializers outInitializers = out.get(variableDescriptor);
VariableInitState outInitState = out.get(variableDescriptor);
if (instruction instanceof ReadValueInstruction) {
JetElement element = ((ReadValueInstruction) instruction).getElement();
boolean error = checkBackingField(variableDescriptor, element);
if (!error && declaredVariables.contains(variableDescriptor)) {
checkIsInitialized(variableDescriptor, element, outInitializers, varWithUninitializedErrorGenerated);
checkIsInitialized(variableDescriptor, element, outInitState, varWithUninitializedErrorGenerated);
}
return;
}
JetElement element = ((WriteValueInstruction) instruction).getlValue();
boolean error = checkBackingField(variableDescriptor, element);
if (!(element instanceof JetExpression)) return;
VariableInitializers inInitializers = in.get(variableDescriptor);
PseudocodeVariablesData.VariableInitState inInitState = in.get(variableDescriptor);
if (!error && !processLocalDeclaration) { // error has been generated before, while processing outer function of this local declaration
error = checkValReassignment(variableDescriptor, (JetExpression) element, inInitializers, varWithValReassignErrorGenerated);
error = checkValReassignment(variableDescriptor, (JetExpression) element, inInitState, varWithValReassignErrorGenerated);
}
if (!error && processClassOrObject) {
error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, inInitializers, outInitializers);
error = checkAssignmentBeforeDeclaration(variableDescriptor, (JetExpression) element, inInitState, outInitState);
}
if (!error && processClassOrObject) {
checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, inInitializers, outInitializers);
checkInitializationUsingBackingField(variableDescriptor, (JetExpression) element, inInitState, outInitState);
}
}
});
@@ -232,11 +233,11 @@ public class JetFlowInformationProvider {
private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor,
@NotNull JetElement element,
@NotNull VariableInitializers variableInitializers,
@NotNull PseudocodeVariablesData.VariableInitState variableInitState,
@NotNull Collection<VariableDescriptor> varWithUninitializedErrorGenerated) {
if (!(element instanceof JetSimpleNameExpression)) return;
boolean isInitialized = variableInitializers.isInitialized();
boolean isInitialized = variableInitState.isInitialized;
if (variableDescriptor instanceof PropertyDescriptor) {
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) {
isInitialized = true;
@@ -256,15 +257,11 @@ public class JetFlowInformationProvider {
private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor,
@NotNull JetExpression expression,
@NotNull VariableInitializers enterInitializers,
@NotNull VariableInitState enterInitState,
@NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) {
boolean isInitializedNotHere = enterInitializers.isInitialized();
Set<JetElement> possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers();
if (possibleLocalInitializers.size() == 1) {
JetElement initializer = possibleLocalInitializers.iterator().next();
if (initializer instanceof JetProperty && initializer == expression.getParent()) {
isInitializedNotHere = false;
}
boolean isInitializedNotHere = enterInitState.isInitialized;
if (expression.getParent() instanceof JetProperty && ((JetProperty)expression).getInitializer() != null) {
isInitializedNotHere = false;
}
boolean hasBackingField = true;
if (variableDescriptor instanceof PropertyDescriptor) {
@@ -307,16 +304,16 @@ public class JetFlowInformationProvider {
return false;
}
private boolean checkAssignmentBeforeDeclaration(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) {
if (!enterInitializers.isDeclared() && !exitInitializers.isDeclared() && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) {
private boolean checkAssignmentBeforeDeclaration(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitState enterInitState, @NotNull VariableInitState exitInitState) {
if (!enterInitState.isDeclared && !exitInitState.isDeclared && !enterInitState.isInitialized && exitInitState.isInitialized) {
trace.report(Errors.INITIALIZATION_BEFORE_DECLARATION.on(expression, variableDescriptor));
return true;
}
return false;
}
private boolean checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull VariableInitializers exitInitializers) {
if (variableDescriptor instanceof PropertyDescriptor && !enterInitializers.isInitialized() && exitInitializers.isInitialized()) {
private boolean checkInitializationUsingBackingField(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitState enterInitState, @NotNull VariableInitState exitInitState) {
if (variableDescriptor instanceof PropertyDescriptor && !enterInitState.isInitialized && exitInitState.isInitialized) {
if (!variableDescriptor.isVar()) return false;
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) return false;
PsiElement property = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), variableDescriptor);
@@ -396,15 +393,15 @@ public class JetFlowInformationProvider {
return false;
}
private void recordInitializedVariables(@NotNull Pseudocode pseudocode, @NotNull Map<Instruction, Edges<Map<VariableDescriptor,VariableInitializers>>> initializersMap) {
Edges<Map<VariableDescriptor, VariableInitializers>> initializers = initializersMap.get(pseudocode.getExitInstruction());
private void recordInitializedVariables(@NotNull Pseudocode pseudocode, @NotNull Map<Instruction, Edges<Map<VariableDescriptor,PseudocodeVariablesData.VariableInitState>>> initializersMap) {
Edges<Map<VariableDescriptor, VariableInitState>> initializers = initializersMap.get(pseudocode.getExitInstruction());
Set<VariableDescriptor> usedVariables = pseudocodeVariablesData.getUsedVariables(pseudocode);
Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode);
for (VariableDescriptor variable : usedVariables) {
if (variable instanceof PropertyDescriptor && declaredVariables.contains(variable)) {
VariableInitializers variableInitializers = initializers.in.get(variable);
if (variableInitializers == null) return;
trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitializers.isInitialized());
PseudocodeVariablesData.VariableInitState variableInitState = initializers.in.get(variable);
if (variableInitState == null) return;
trace.record(BindingContext.IS_INITIALIZED, (PropertyDescriptor) variable, variableInitState.isInitialized);
}
}
}
@@ -413,13 +410,13 @@ public class JetFlowInformationProvider {
// "Unused variable" & "unused value" analyses
public void markUnusedVariables() {
Map<Instruction, Edges<Map<VariableDescriptor, VariableUseStatus>>> variableStatusData = pseudocodeVariablesData.getVariableUseStatusData();
InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableUseStatus>> variableStatusAnalyzeStrategy =
new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableUseStatus>>() {
Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> variableStatusData = pseudocodeVariablesData.getVariableUseStatusData();
InstructionDataAnalyzeStrategy<Map<VariableDescriptor, VariableUseState>> variableStatusAnalyzeStrategy =
new InstructionDataAnalyzeStrategy<Map<VariableDescriptor, PseudocodeVariablesData.VariableUseState>>() {
@Override
public void execute(@NotNull Instruction instruction,
@Nullable Map<VariableDescriptor, VariableUseStatus> in,
@Nullable Map<VariableDescriptor, VariableUseStatus> out) {
@Nullable Map<VariableDescriptor, PseudocodeVariablesData.VariableUseState> in,
@Nullable Map<VariableDescriptor, VariableUseState> out) {
assert in != null && out != null;
Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(instruction.getOwner());
@@ -427,11 +424,11 @@ public class JetFlowInformationProvider {
trace.getBindingContext());
if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) ||
!DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) return;
VariableUseStatus variableUseStatus = in.get(variableDescriptor);
PseudocodeVariablesData.VariableUseState variableUseState = in.get(variableDescriptor);
if (instruction instanceof WriteValueInstruction) {
if (trace.get(CAPTURED_IN_CLOSURE, variableDescriptor)) return;
JetElement element = ((WriteValueInstruction) instruction).getElement();
if (variableUseStatus != VariableUseStatus.LAST_READ) {
if (variableUseState != LAST_READ) {
if (element instanceof JetBinaryExpression &&
((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) {
JetExpression right = ((JetBinaryExpression) element).getRight();
@@ -452,7 +449,7 @@ public class JetFlowInformationProvider {
if (element instanceof JetNamedDeclaration) {
PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier();
if (nameIdentifier == null) return;
if (variableUseStatus == null || variableUseStatus == VariableUseStatus.UNUSED) {
if (variableUseState == null || variableUseState == UNUSED) {
if (element instanceof JetProperty) {
trace.report(Errors.UNUSED_VARIABLE.on((JetProperty) element, variableDescriptor));
}
@@ -470,10 +467,10 @@ public class JetFlowInformationProvider {
}
}
}
else if (variableUseStatus == VariableUseStatus.ONLY_WRITTEN_NEVER_READ &&element instanceof JetProperty) {
else if (variableUseState == ONLY_WRITTEN_NEVER_READ &&element instanceof JetProperty) {
trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, variableDescriptor));
}
else if (variableUseStatus == VariableUseStatus.LAST_WRITTEN && element instanceof JetProperty) {
else if (variableUseState == LAST_WRITTEN && element instanceof JetProperty) {
JetExpression initializer = ((JetProperty) element).getInitializer();
if (initializer != null) {
trace.report(Errors.VARIABLE_WITH_REDUNDANT_INITIALIZER.on(initializer, variableDescriptor));
@@ -181,16 +181,6 @@ public class PseudocodeTraverser {
return new Edges<T>(in, out);
}
@NotNull
public T getIn() {
return in;
}
@NotNull
public T getOut() {
return out;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -44,8 +44,8 @@ public class PseudocodeVariablesData {
private final Map<Pseudocode, Set<VariableDescriptor>> declaredVariablesInEachDeclaration = Maps.newHashMap();
private final Map<Pseudocode, Set<VariableDescriptor>> usedVariablesInEachDeclaration = Maps.newHashMap();
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitializers>>> variableInitializersMap;
private Map<Instruction, Edges<Map<VariableDescriptor, VariableUseStatus>>> variableStatusMap;
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> variableInitializersMap;
private Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> variableStatusMap;
public PseudocodeVariablesData(@NotNull Pseudocode pseudocode, @NotNull BindingContext bindingContext) {
this.pseudocode = pseudocode;
@@ -102,7 +102,7 @@ public class PseudocodeVariablesData {
// variable initializers
@NotNull
public Map<Instruction, Edges<Map<VariableDescriptor, VariableInitializers>>> getVariableInitializers() {
public Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> getVariableInitializers() {
if (variableInitializersMap == null) {
variableInitializersMap = getVariableInitializers(pseudocode);
}
@@ -110,23 +110,23 @@ public class PseudocodeVariablesData {
}
@NotNull
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitializers>>> getVariableInitializers(@NotNull Pseudocode pseudocode) {
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> getVariableInitializers(@NotNull Pseudocode pseudocode) {
Set<VariableDescriptor> usedVariables = getUsedVariables(pseudocode);
Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode);
Map<VariableDescriptor, VariableInitializers> initialMap = Collections.emptyMap();
final Map<VariableDescriptor, VariableInitializers> initialMapForStartInstruction = prepareInitializersMapForStartInstruction(
Map<VariableDescriptor, VariableInitState> initialMap = Collections.emptyMap();
final Map<VariableDescriptor, VariableInitState> initialMapForStartInstruction = prepareInitializersMapForStartInstruction(
usedVariables, declaredVariables);
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitializers>>> variableInitializersMap = PseudocodeTraverser.collectData(
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> variableInitializersMap = PseudocodeTraverser.collectData(
pseudocode, /* directOrder = */ true, /* lookInside = */ false,
initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitializers>>() {
initialMap, initialMapForStartInstruction, new PseudocodeTraverser.InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
@Override
public Edges<Map<VariableDescriptor, VariableInitializers>> execute(
@NotNull Instruction instruction, @NotNull Collection<Map<VariableDescriptor, VariableInitializers>> incomingEdgesData) {
public Edges<Map<VariableDescriptor, VariableInitState>> execute(
@NotNull Instruction instruction, @NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData) {
Map<VariableDescriptor, VariableInitializers> enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData);
Map<VariableDescriptor, VariableInitializers> exitInstructionData =
Map<VariableDescriptor, VariableInitState> enterInstructionData = mergeIncomingEdgesDataForInitializers(incomingEdgesData);
Map<VariableDescriptor, VariableInitState> exitInstructionData =
addVariableInitializerFromCurrentInstructionIfAny(instruction, enterInstructionData);
return Edges.create(enterInstructionData, exitInstructionData);
}
@@ -135,7 +135,7 @@ public class PseudocodeVariablesData {
for (LocalDeclarationInstruction localDeclarationInstruction : pseudocode.getLocalDeclarations()) {
Pseudocode localPseudocode = localDeclarationInstruction.getBody();
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitializers>>> initializersForLocalDeclaration = getVariableInitializers(localPseudocode);
Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> initializersForLocalDeclaration = getVariableInitializers(localPseudocode);
for (Instruction instruction : initializersForLocalDeclaration.keySet()) {
//todo
@@ -149,51 +149,51 @@ public class PseudocodeVariablesData {
}
@NotNull
private Map<VariableDescriptor, VariableInitializers> prepareInitializersMapForStartInstruction(
private Map<VariableDescriptor, VariableInitState> prepareInitializersMapForStartInstruction(
@NotNull Collection<VariableDescriptor> usedVariables,
@NotNull Collection<VariableDescriptor> declaredVariables) {
Map<VariableDescriptor, VariableInitializers> initialMapForStartInstruction = Maps.newHashMap();
VariableInitializers isInitializedForExternalVariable = new VariableInitializers(true);
VariableInitializers isNotInitializedForDeclaredVariable = new VariableInitializers(false);
Map<VariableDescriptor, VariableInitState> initialMapForStartInstruction = Maps.newHashMap();
VariableInitState initializedForExternalVariable = new VariableInitState(true);
VariableInitState notInitializedForDeclaredVariable = new VariableInitState(false);
for (VariableDescriptor variable : usedVariables) {
if (declaredVariables.contains(variable)) {
initialMapForStartInstruction.put(variable, isNotInitializedForDeclaredVariable);
initialMapForStartInstruction.put(variable, notInitializedForDeclaredVariable);
}
else {
initialMapForStartInstruction.put(variable, isInitializedForExternalVariable);
initialMapForStartInstruction.put(variable, initializedForExternalVariable);
}
}
return initialMapForStartInstruction;
}
@NotNull
private Map<VariableDescriptor, VariableInitializers> mergeIncomingEdgesDataForInitializers(
@NotNull Collection<Map<VariableDescriptor, VariableInitializers>> incomingEdgesData) {
private Map<VariableDescriptor, VariableInitState> mergeIncomingEdgesDataForInitializers(
@NotNull Collection<Map<VariableDescriptor, VariableInitState>> incomingEdgesData) {
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
for (Map<VariableDescriptor, VariableInitializers> edgeData : incomingEdgesData) {
for (Map<VariableDescriptor, VariableInitState> edgeData : incomingEdgesData) {
variablesInScope.addAll(edgeData.keySet());
}
Map<VariableDescriptor, VariableInitializers> enterInstructionData = Maps.newHashMap();
Map<VariableDescriptor, VariableInitState> enterInstructionData = Maps.newHashMap();
for (VariableDescriptor variable : variablesInScope) {
Set<VariableInitializers> edgesDataForVariable = Sets.newHashSet();
for (Map<VariableDescriptor, VariableInitializers> edgeData : incomingEdgesData) {
VariableInitializers initializers = edgeData.get(variable);
if (initializers != null) {
edgesDataForVariable.add(initializers);
Set<VariableInitState> edgesDataForVariable = Sets.newHashSet();
for (Map<VariableDescriptor, VariableInitState> edgeData : incomingEdgesData) {
VariableInitState initState = edgeData.get(variable);
if (initState != null) {
edgesDataForVariable.add(initState);
}
}
enterInstructionData.put(variable, new VariableInitializers(edgesDataForVariable));
enterInstructionData.put(variable, new VariableInitState(edgesDataForVariable));
}
return enterInstructionData;
}
@NotNull
private Map<VariableDescriptor, VariableInitializers> addVariableInitializerFromCurrentInstructionIfAny(
@NotNull Instruction instruction, @NotNull Map<VariableDescriptor, VariableInitializers> enterInstructionData) {
private Map<VariableDescriptor, VariableInitState> addVariableInitializerFromCurrentInstructionIfAny(
@NotNull Instruction instruction, @NotNull Map<VariableDescriptor, VariableInitState> enterInstructionData) {
if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) {
return enterInstructionData;
@@ -202,21 +202,22 @@ public class PseudocodeVariablesData {
if (variable == null) {
return enterInstructionData;
}
Map<VariableDescriptor, VariableInitializers> exitInstructionData = Maps.newHashMap(enterInstructionData);
Map<VariableDescriptor, VariableInitState> exitInstructionData = Maps.newHashMap(enterInstructionData);
if (instruction instanceof WriteValueInstruction) {
VariableInitializers enterInitializers = enterInstructionData.get(variable);
VariableInitializers initializationAtThisElement = new VariableInitializers(((WriteValueInstruction) instruction).getElement(), enterInitializers);
VariableInitState enterInitState = enterInstructionData.get(variable);
VariableInitState initializationAtThisElement =
new VariableInitState(((WriteValueInstruction) instruction).getElement() instanceof JetProperty, enterInitState);
exitInstructionData.put(variable, initializationAtThisElement);
}
else {
VariableInitializers enterInitializers = enterInstructionData.get(variable);
if (enterInitializers == null || !enterInitializers.isInitialized() || !enterInitializers.isDeclared()) {
else { // instruction instanceof VariableDeclarationInstruction
VariableInitState enterInitState = enterInstructionData.get(variable);
if (enterInitState == null || !enterInitState.isInitialized || !enterInitState.isDeclared) {
JetElement element = ((VariableDeclarationInstruction) instruction).getElement();
if (element instanceof JetProperty) {
JetProperty property = (JetProperty) element;
if (property.getInitializer() == null) {
boolean isInitialized = enterInitializers != null && enterInitializers.isInitialized();
VariableInitializers variableDeclarationInfo = new VariableInitializers(isInitialized, true);
boolean isInitialized = enterInitState != null && enterInitState.isInitialized;
VariableInitState variableDeclarationInfo = new VariableInitState(isInitialized, true);
exitInstructionData.put(variable, variableDeclarationInfo);
}
}
@@ -228,23 +229,23 @@ public class PseudocodeVariablesData {
// variable use
@NotNull
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseStatus>>> getVariableUseStatusData() {
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
if (variableStatusMap == null) {
Map<VariableDescriptor, VariableUseStatus> sinkInstructionData = Maps.newHashMap();
Map<VariableDescriptor, VariableUseState> sinkInstructionData = Maps.newHashMap();
for (VariableDescriptor usedVariable : usedVariablesInEachDeclaration.get(pseudocode)) {
sinkInstructionData.put(usedVariable, VariableUseStatus.UNUSED);
sinkInstructionData.put(usedVariable, VariableUseState.UNUSED);
}
InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseStatus>> collectVariableUseStatusStrategy = new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseStatus>>() {
InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>> collectVariableUseStatusStrategy = new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
@Override
public Edges<Map<VariableDescriptor, VariableUseStatus>> execute(@NotNull Instruction instruction,
@NotNull Collection<Map<VariableDescriptor, VariableUseStatus>> incomingEdgesData) {
public Edges<Map<VariableDescriptor, VariableUseState>> execute(@NotNull Instruction instruction,
@NotNull Collection<Map<VariableDescriptor, VariableUseState>> incomingEdgesData) {
Map<VariableDescriptor, VariableUseStatus> enterResult = Maps.newHashMap();
for (Map<VariableDescriptor, VariableUseStatus> edgeData : incomingEdgesData) {
for (Map.Entry<VariableDescriptor, VariableUseStatus> entry : edgeData.entrySet()) {
Map<VariableDescriptor, VariableUseState> enterResult = Maps.newHashMap();
for (Map<VariableDescriptor, VariableUseState> edgeData : incomingEdgesData) {
for (Map.Entry<VariableDescriptor, VariableUseState> entry : edgeData.entrySet()) {
VariableDescriptor variableDescriptor = entry.getKey();
VariableUseStatus variableUseStatus = entry.getValue();
enterResult.put(variableDescriptor, variableUseStatus.merge(enterResult.get(variableDescriptor)));
VariableUseState variableUseState = entry.getValue();
enterResult.put(variableDescriptor, variableUseState.merge(enterResult.get(variableDescriptor)));
}
}
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(instruction, true,
@@ -253,109 +254,90 @@ public class PseudocodeVariablesData {
(!(instruction instanceof ReadValueInstruction) && !(instruction instanceof WriteValueInstruction))) {
return Edges.create(enterResult, enterResult);
}
Map<VariableDescriptor, VariableUseStatus> exitResult = Maps.newHashMap(enterResult);
Map<VariableDescriptor, VariableUseState> exitResult = Maps.newHashMap(enterResult);
if (instruction instanceof ReadValueInstruction) {
exitResult.put(variableDescriptor, VariableUseStatus.LAST_READ);
exitResult.put(variableDescriptor, VariableUseState.LAST_READ);
}
else {
VariableUseStatus variableUseStatus = enterResult.get(variableDescriptor);
if (variableUseStatus == null) {
variableUseStatus = VariableUseStatus.UNUSED;
else { //instruction instanceof WriteValueInstruction
VariableUseState variableUseState = enterResult.get(variableDescriptor);
if (variableUseState == null) {
variableUseState = VariableUseState.UNUSED;
}
switch (variableUseStatus) {
switch (variableUseState) {
case UNUSED:
case ONLY_WRITTEN_NEVER_READ:
exitResult.put(variableDescriptor, VariableUseStatus.ONLY_WRITTEN_NEVER_READ);
exitResult.put(variableDescriptor, VariableUseState.ONLY_WRITTEN_NEVER_READ);
break;
case LAST_WRITTEN:
case LAST_READ:
exitResult.put(variableDescriptor, VariableUseStatus.LAST_WRITTEN);
exitResult.put(variableDescriptor, VariableUseState.LAST_WRITTEN);
}
}
return Edges.create(enterResult, exitResult);
}
};
variableStatusMap = PseudocodeTraverser.collectData(pseudocode, false, true,
Collections.<VariableDescriptor, VariableUseStatus>emptyMap(),
Collections.<VariableDescriptor, VariableUseState>emptyMap(),
sinkInstructionData, collectVariableUseStatusStrategy);
}
return variableStatusMap;
}
public static class VariableInitializers {
private final Set<JetElement> possibleLocalInitializers = Sets.newHashSet();
private boolean isInitialized;
private boolean isDeclared;
public static class VariableInitState {
public final boolean isInitialized;
public final boolean isDeclared;
public VariableInitializers(boolean isInitialized) {
public VariableInitState(boolean isInitialized) {
this(isInitialized, false);
}
public VariableInitializers(boolean isInitialized, boolean isDeclared) {
public VariableInitState(boolean isInitialized, boolean isDeclared) {
this.isInitialized = isInitialized;
this.isDeclared = isDeclared;
}
public VariableInitializers(JetElement element, @Nullable VariableInitializers previous) {
public VariableInitState(boolean isDeclaredHere, @Nullable VariableInitState mergedEdgesData) {
isInitialized = true;
isDeclared = element instanceof JetProperty || (previous != null && previous.isDeclared());
possibleLocalInitializers.add(element);
isDeclared = isDeclaredHere || (mergedEdgesData != null && mergedEdgesData.isDeclared);
}
public VariableInitializers(Set<VariableInitializers> edgesData) {
isInitialized = true;
isDeclared = true;
for (VariableInitializers edgeData : edgesData) {
public VariableInitState(@NotNull Set<VariableInitState> edgesData) {
boolean isInitialized = true;
boolean isDeclared = true;
for (VariableInitState edgeData : edgesData) {
if (!edgeData.isInitialized) {
isInitialized = false;
}
if (!edgeData.isDeclared) {
isDeclared = false;
}
possibleLocalInitializers.addAll(edgeData.possibleLocalInitializers);
}
}
public Set<JetElement> getPossibleLocalInitializers() {
return possibleLocalInitializers;
}
public boolean isInitialized() {
return isInitialized;
}
public boolean isDeclared() {
return isDeclared;
this.isInitialized = isInitialized;
this.isDeclared = isDeclared;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof VariableInitializers)) return false;
if (!(o instanceof VariableInitState)) return false;
VariableInitializers that = (VariableInitializers) o;
VariableInitState that = (VariableInitState) o;
if (isDeclared != that.isDeclared) return false;
if (isInitialized != that.isInitialized) return false;
if (possibleLocalInitializers != null
? !possibleLocalInitializers.equals(that.possibleLocalInitializers)
: that.possibleLocalInitializers != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = possibleLocalInitializers != null ? possibleLocalInitializers.hashCode() : 0;
result = 31 * result + (isInitialized ? 1 : 0);
int result = (isInitialized ? 1 : 0);
result = 31 * result + (isDeclared ? 1 : 0);
return result;
}
}
public static enum VariableUseStatus {
public static enum VariableUseState {
LAST_READ(3),
LAST_WRITTEN(2),
ONLY_WRITTEN_NEVER_READ(1),
@@ -363,13 +345,13 @@ public class PseudocodeVariablesData {
private final int importance;
VariableUseStatus(int importance) {
VariableUseState(int importance) {
this.importance = importance;
}
public VariableUseStatus merge(@Nullable VariableUseStatus variableUseStatus) {
if (variableUseStatus == null || importance > variableUseStatus.importance) return this;
return variableUseStatus;
public VariableUseState merge(@Nullable VariableUseState variableUseState) {
if (variableUseState == null || importance > variableUseState.importance) return this;
return variableUseState;
}
}
}