some draft for inline functions (to return to it after M1)
This commit is contained in:
@@ -5,10 +5,12 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
@@ -590,6 +592,17 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitCallExpression(JetCallExpression expression) {
|
public void visitCallExpression(JetCallExpression expression) {
|
||||||
|
//inline functions after M1
|
||||||
|
// ResolvedCall<? extends CallableDescriptor> resolvedCall = trace.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
|
||||||
|
// assert resolvedCall != null;
|
||||||
|
// CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||||
|
// PsiElement element = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, resultingDescriptor);
|
||||||
|
// if (element instanceof JetNamedFunction) {
|
||||||
|
// JetNamedFunction namedFunction = (JetNamedFunction) element;
|
||||||
|
// if (namedFunction.hasModifier(JetTokens.INLINE_KEYWORD)) {
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
for (JetTypeProjection typeArgument : expression.getTypeArguments()) {
|
for (JetTypeProjection typeArgument : expression.getTypeArguments()) {
|
||||||
value(typeArgument, false);
|
value(typeArgument, false);
|
||||||
}
|
}
|
||||||
@@ -726,6 +739,9 @@ public class JetControlFlowProcessor {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
|
public void visitObjectDeclaration(JetObjectDeclaration declaration) {
|
||||||
|
// for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) {
|
||||||
|
// value(delegationSpecifier, inCondition);
|
||||||
|
// }
|
||||||
Queue<Label> declarationLabels = new LinkedList<Label>();
|
Queue<Label> declarationLabels = new LinkedList<Label>();
|
||||||
List<JetDeclaration> declarations = declaration.getDeclarations();
|
List<JetDeclaration> declarations = declaration.getDeclarations();
|
||||||
for (JetDeclaration localDeclaration : declarations) {
|
for (JetDeclaration localDeclaration : declarations) {
|
||||||
@@ -734,27 +750,19 @@ public class JetControlFlowProcessor {
|
|||||||
builder.nondeterministicJump(Lists.newArrayList(declarationLabels));
|
builder.nondeterministicJump(Lists.newArrayList(declarationLabels));
|
||||||
for (JetDeclaration localDeclaration : declarations) {
|
for (JetDeclaration localDeclaration : declarations) {
|
||||||
if (localDeclaration instanceof JetNamedDeclaration) {
|
if (localDeclaration instanceof JetNamedDeclaration) {
|
||||||
if (localDeclaration instanceof JetFunction) {
|
if (localDeclaration instanceof JetDeclarationWithBody) {
|
||||||
//TODO
|
JetExpression bodyExpression = ((JetDeclarationWithBody) localDeclaration).getBodyExpression();
|
||||||
generate(localDeclaration, ((JetFunction) localDeclaration).getBodyExpression());
|
generate(localDeclaration, bodyExpression != null ? bodyExpression : localDeclaration);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
generate(localDeclaration, localDeclaration);
|
generate(localDeclaration, localDeclaration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//todo
|
|
||||||
generate(declaration, localDeclaration);
|
generate(declaration, localDeclaration);
|
||||||
}
|
}
|
||||||
builder.bindLabel(declarationLabels.remove());
|
builder.bindLabel(declarationLabels.remove());
|
||||||
}
|
}
|
||||||
// for (JetDelegationSpecifier delegationSpecifier : declaration.getDelegationSpecifiers()) {
|
|
||||||
// value(delegationSpecifier, inCondition);
|
|
||||||
// }
|
|
||||||
// for (JetDeclaration jetDeclaration : declaration.getDeclarations()) {
|
|
||||||
// //FOR_LOCAL_CLASSES.
|
|
||||||
// value(jetDeclaration, false);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -8,10 +8,13 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import org.jetbrains.jet.lang.cfg.pseudocode.*;
|
import org.jetbrains.jet.lang.cfg.pseudocode.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.LocalVariableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.LocalVariableDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -256,103 +259,25 @@ public class JetFlowInformationProvider {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
private <D> Map<Instruction, D> traverseInstructionGraphUntilFactsStabilization(
|
public void markUninitializedVariables(@NotNull JetElement subroutine, List<? extends VariableDescriptor> initializedVariables) {
|
||||||
Pseudocode pseudocode,
|
|
||||||
InstructionsMergeHandler<D> instructionsMergeHandler,
|
|
||||||
D initialDataValue,
|
|
||||||
D initialDataValueForEnterInstruction,
|
|
||||||
boolean straightDirection) {
|
|
||||||
Map<Instruction, D> dataMap = Maps.newHashMap();
|
|
||||||
initializeDataMap(dataMap, pseudocode, initialDataValue);
|
|
||||||
dataMap.put(pseudocode.getEnterInstruction(), initialDataValueForEnterInstruction);
|
|
||||||
|
|
||||||
boolean[] changed = new boolean[1];
|
|
||||||
changed[0] = true;
|
|
||||||
while (changed[0]) {
|
|
||||||
changed[0] = false;
|
|
||||||
traverseSubGraph(pseudocode, instructionsMergeHandler, Collections.<Instruction>emptyList(), straightDirection, dataMap, changed, false);
|
|
||||||
}
|
|
||||||
return dataMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
private <D> void initializeDataMap(
|
|
||||||
Map<Instruction, D> dataMap,
|
|
||||||
Pseudocode pseudocode,
|
|
||||||
D initialDataValue) {
|
|
||||||
List<Instruction> instructions = pseudocode.getInstructions();
|
|
||||||
for (Instruction instruction : instructions) {
|
|
||||||
dataMap.put(instruction, initialDataValue);
|
|
||||||
if (instruction instanceof LocalDeclarationInstruction) {
|
|
||||||
initializeDataMap(dataMap, ((LocalDeclarationInstruction) instruction).getBody(), initialDataValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private <D> void traverseSubGraph(
|
|
||||||
Pseudocode pseudocode,
|
|
||||||
InstructionsMergeHandler<D> instructionsMergeHandler,
|
|
||||||
Collection<Instruction> previousSubGraphInstructions,
|
|
||||||
boolean straightDirection,
|
|
||||||
Map<Instruction, D> dataMap,
|
|
||||||
boolean[] changed,
|
|
||||||
boolean isLocal) {
|
|
||||||
List<Instruction> instructions = pseudocode.getInstructions();
|
|
||||||
SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction();
|
|
||||||
for (Instruction instruction : instructions) {
|
|
||||||
if (!isLocal && instruction instanceof SubroutineEnterInstruction) continue;
|
|
||||||
|
|
||||||
Collection<Instruction> allPreviousInstructions;
|
|
||||||
Collection<Instruction> previousInstructions = straightDirection
|
|
||||||
? instruction.getPreviousInstructions()
|
|
||||||
: instruction.getNextInstructions();
|
|
||||||
|
|
||||||
if (instruction == enterInstruction && !previousSubGraphInstructions.isEmpty()) {
|
|
||||||
allPreviousInstructions = Lists.newArrayList(previousInstructions);
|
|
||||||
allPreviousInstructions.addAll(previousSubGraphInstructions);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
allPreviousInstructions = previousInstructions;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instruction instanceof LocalDeclarationInstruction) {
|
|
||||||
Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody();
|
|
||||||
traverseSubGraph(subroutinePseudocode, instructionsMergeHandler, previousInstructions, straightDirection, dataMap, changed, true);
|
|
||||||
}
|
|
||||||
D previousDataValue = dataMap.get(instruction);
|
|
||||||
|
|
||||||
Collection<D> incomingEdgesData = Sets.newHashSet();
|
|
||||||
|
|
||||||
for (Instruction previousInstruction : allPreviousInstructions) {
|
|
||||||
incomingEdgesData.add(dataMap.get(previousInstruction));
|
|
||||||
}
|
|
||||||
D mergedData = instructionsMergeHandler.merge(instruction, incomingEdgesData);
|
|
||||||
if (!mergedData.equals(previousDataValue)) {
|
|
||||||
changed[0] = true;
|
|
||||||
dataMap.put(instruction, mergedData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void markUninitializedVariables(@NotNull JetElement subroutine) {
|
|
||||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||||
assert pseudocode != null;
|
assert pseudocode != null;
|
||||||
|
|
||||||
Collection<Instruction> instructions = pseudocode.getInstructions();
|
JetControlFlowGraphTraverser.InstructionsMergeStrategy<Map<VariableDescriptor, InitializationPoints>> instructionsMergeStrategy = new JetControlFlowGraphTraverser.InstructionsMergeStrategy<Map<VariableDescriptor, InitializationPoints>>() {
|
||||||
InstructionsMergeHandler<Map<LocalVariableDescriptor, InitializationPoints>> instructionsMergeHandler = new InstructionsMergeHandler<Map<LocalVariableDescriptor, InitializationPoints>>() {
|
|
||||||
@Override
|
@Override
|
||||||
public Map<LocalVariableDescriptor, InitializationPoints> merge(
|
public Map<VariableDescriptor, InitializationPoints> execute(
|
||||||
Instruction instruction,
|
Instruction instruction,
|
||||||
Collection<Map<LocalVariableDescriptor, InitializationPoints>> incomingEdgesData) {
|
Collection<Map<VariableDescriptor, InitializationPoints>> incomingEdgesData) {
|
||||||
|
|
||||||
Set<LocalVariableDescriptor> variablesInScope = Sets.newHashSet();
|
Set<VariableDescriptor> variablesInScope = Sets.newHashSet();
|
||||||
for (Map<LocalVariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) {
|
for (Map<VariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) {
|
||||||
variablesInScope.addAll(edgePointsMap.keySet());
|
variablesInScope.addAll(edgePointsMap.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<LocalVariableDescriptor, InitializationPoints> pointsMap = Maps.newHashMap();
|
Map<VariableDescriptor, InitializationPoints> pointsMap = Maps.newHashMap();
|
||||||
for (LocalVariableDescriptor variable : variablesInScope) {
|
for (VariableDescriptor variable : variablesInScope) {
|
||||||
Set<InitializationPoints> edgesDataForVariable = Sets.newHashSet();
|
Set<InitializationPoints> edgesDataForVariable = Sets.newHashSet();
|
||||||
for (Map<LocalVariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) {
|
for (Map<VariableDescriptor, InitializationPoints> edgePointsMap : incomingEdgesData) {
|
||||||
InitializationPoints points = edgePointsMap.get(variable);
|
InitializationPoints points = edgePointsMap.get(variable);
|
||||||
if (points != null) {
|
if (points != null) {
|
||||||
edgesDataForVariable.add(points);
|
edgesDataForVariable.add(points);
|
||||||
@@ -362,81 +287,95 @@ public class JetFlowInformationProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (instruction instanceof WriteValueInstruction) {
|
if (instruction instanceof WriteValueInstruction) {
|
||||||
LocalVariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
||||||
// DeclarationDescriptor descriptor = null;
|
|
||||||
// JetElement lValue = ((WriteValueInstruction) instruction).getlValue();
|
|
||||||
// if (lValue instanceof JetProperty || lValue instanceof JetParameter) {
|
|
||||||
// descriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, lValue);
|
|
||||||
// }
|
|
||||||
// else if (lValue instanceof JetSimpleNameExpression) {
|
|
||||||
// descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) lValue);
|
|
||||||
// }
|
|
||||||
// if (descriptor instanceof LocalVariableDescriptor) {
|
|
||||||
// LocalVariableDescriptor variableDescriptor = (LocalVariableDescriptor) descriptor;
|
|
||||||
InitializationPoints initializationAtThisPoint = new InitializationPoints(((WriteValueInstruction) instruction).getElement());
|
InitializationPoints initializationAtThisPoint = new InitializationPoints(((WriteValueInstruction) instruction).getElement());
|
||||||
pointsMap.put(variableDescriptor, initializationAtThisPoint);
|
pointsMap.put(variableDescriptor, initializationAtThisPoint);
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pointsMap;
|
return pointsMap;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Set<LocalVariableDescriptor> localVariables = collectAllLocalVariables(pseudocode);
|
Set<VariableDescriptor> localVariables = collectAllLocalVariables(pseudocode);
|
||||||
Map<LocalVariableDescriptor, InitializationPoints> initialMapForStartInstruction = Maps.newHashMap();
|
Map<VariableDescriptor, InitializationPoints> initialMapForStartInstruction = Maps.newHashMap();
|
||||||
InitializationPoints initialPoints = new InitializationPoints();
|
InitializationPoints initialPointsForLocalVariable = new InitializationPoints(true);
|
||||||
for (LocalVariableDescriptor variable : localVariables) {
|
for (VariableDescriptor variable : localVariables) {
|
||||||
initialMapForStartInstruction.put(variable, initialPoints);
|
initialMapForStartInstruction.put(variable, initialPointsForLocalVariable);
|
||||||
}
|
}
|
||||||
Map<Instruction, Map<LocalVariableDescriptor, InitializationPoints>> dataMap =
|
InitializationPoints initialPointsForParameter = new InitializationPoints(false);
|
||||||
traverseInstructionGraphUntilFactsStabilization(pseudocode, instructionsMergeHandler, Collections.<LocalVariableDescriptor, InitializationPoints>emptyMap(), initialMapForStartInstruction, true);
|
for (VariableDescriptor initializedVariable : initializedVariables) {
|
||||||
|
initialMapForStartInstruction.put(initializedVariable, initialPointsForParameter);
|
||||||
|
}
|
||||||
|
final Map<Instruction, Map<VariableDescriptor, InitializationPoints>> dataMap =
|
||||||
|
JetControlFlowGraphTraverser.traverseInstructionGraphUntilFactsStabilization(pseudocode, instructionsMergeStrategy, Collections.<VariableDescriptor, InitializationPoints>emptyMap(), initialMapForStartInstruction, true);
|
||||||
|
|
||||||
InstructionDataAnalyzer<Map<LocalVariableDescriptor, InitializationPoints>> instructionDataAnalyzer = new InstructionDataAnalyzer<Map<LocalVariableDescriptor, InitializationPoints>>() {
|
JetControlFlowGraphTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() {
|
||||||
@Override
|
@Override
|
||||||
public void analyze(Instruction instruction, Map<Instruction, Map<LocalVariableDescriptor, InitializationPoints>> dataMap) {
|
public void execute(Instruction instruction) {
|
||||||
Map<LocalVariableDescriptor, InitializationPoints> variablesData = dataMap.get(instruction);
|
Map<VariableDescriptor, InitializationPoints> variablesData = dataMap.get(instruction);
|
||||||
if (instruction instanceof ReadValueInstruction) {
|
if (instruction instanceof ReadValueInstruction) {
|
||||||
LocalVariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
||||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||||
if (element instanceof JetSimpleNameExpression && variableDescriptor != null) {
|
if (element instanceof JetSimpleNameExpression && variableDescriptor instanceof LocalVariableDescriptor) {
|
||||||
// DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
|
|
||||||
// if (descriptor instanceof LocalVariableDescriptor) {
|
|
||||||
InitializationPoints initializationPoints = variablesData.get(variableDescriptor);
|
InitializationPoints initializationPoints = variablesData.get(variableDescriptor);
|
||||||
assert initializationPoints != null;
|
assert initializationPoints != null;
|
||||||
if (initializationPoints.canBeUninitialized) {
|
if (initializationPoints.canBeUninitialized) {
|
||||||
trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor));
|
trace.report(Errors.UNINITIALIZED_VARIABLE.on((JetSimpleNameExpression) element, variableDescriptor));
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (instruction instanceof WriteValueInstruction) {
|
else if (instruction instanceof WriteValueInstruction) {
|
||||||
JetElement element = ((WriteValueInstruction) instruction).getlValue();
|
JetElement element = ((WriteValueInstruction) instruction).getlValue();
|
||||||
LocalVariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
||||||
if (element instanceof JetSimpleNameExpression && variableDescriptor != null) {
|
if (element instanceof JetSimpleNameExpression && variableDescriptor != null) {
|
||||||
// DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
|
|
||||||
// if (descriptor instanceof LocalVariableDescriptor) {
|
|
||||||
InitializationPoints initializationPoints = variablesData.get(variableDescriptor);
|
InitializationPoints initializationPoints = variablesData.get(variableDescriptor);
|
||||||
assert initializationPoints != null;
|
assert initializationPoints != null;
|
||||||
if (initializationPoints.hasPossibleInitializers() && !variableDescriptor.isVar()) {
|
if (initializationPoints.hasPossibleInitializers() && !variableDescriptor.isVar()) {
|
||||||
trace.report(Errors.VAL_REASSIGNMENT.on((JetSimpleNameExpression) element, variableDescriptor));
|
trace.report(Errors.VAL_REASSIGNMENT.on((JetSimpleNameExpression) element, variableDescriptor));
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
traverseAndAnalyzeInstructionGraph(instructions, dataMap, instructionDataAnalyzer);
|
}
|
||||||
|
|
||||||
|
public void markNotOnlyInvokedFunctionVariables(@NotNull JetElement subroutine, List<? extends VariableDescriptor> variables) {
|
||||||
|
final List<VariableDescriptor> functionVariables = Lists.newArrayList();
|
||||||
|
for (VariableDescriptor variable : variables) {
|
||||||
|
if (JetStandardClasses.isFunctionType(variable.getReturnType())) {
|
||||||
|
functionVariables.add(variable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||||
|
assert pseudocode != null;
|
||||||
|
|
||||||
|
JetControlFlowGraphTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() {
|
||||||
|
@Override
|
||||||
|
public void execute(Instruction instruction) {
|
||||||
|
if (instruction instanceof ReadValueInstruction) {
|
||||||
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
||||||
|
if (variableDescriptor != null && functionVariables.contains(variableDescriptor)) {
|
||||||
|
//check that we only invoke this variable
|
||||||
|
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||||
|
if (element instanceof JetSimpleNameExpression && !(element.getParent() instanceof JetCallExpression)) {
|
||||||
|
trace.report(Errors.FUNCTION_PARAMETERS_OF_INLINE_FUNCTION.on((JetSimpleNameExpression)element, variableDescriptor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private LocalVariableDescriptor extractVariableDescriptorIfAny(Instruction instruction) {
|
private VariableDescriptor extractVariableDescriptorIfAny(Instruction instruction) {
|
||||||
LocalVariableDescriptor variableDescriptor = null;
|
VariableDescriptor variableDescriptor = null;
|
||||||
if (instruction instanceof ReadValueInstruction) {
|
if (instruction instanceof ReadValueInstruction) {
|
||||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||||
if (element instanceof JetSimpleNameExpression) {
|
if (element instanceof JetSimpleNameExpression) {
|
||||||
DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
|
DeclarationDescriptor descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) element);
|
||||||
if (descriptor instanceof LocalVariableDescriptor) {
|
if (descriptor instanceof VariableDescriptor) {
|
||||||
variableDescriptor = (LocalVariableDescriptor) descriptor;
|
variableDescriptor = (VariableDescriptor) descriptor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,51 +388,34 @@ public class JetFlowInformationProvider {
|
|||||||
else if (lValue instanceof JetSimpleNameExpression) {
|
else if (lValue instanceof JetSimpleNameExpression) {
|
||||||
descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) lValue);
|
descriptor = trace.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) lValue);
|
||||||
}
|
}
|
||||||
if (descriptor instanceof LocalVariableDescriptor) {
|
if (descriptor instanceof VariableDescriptor) {
|
||||||
variableDescriptor = (LocalVariableDescriptor) descriptor;
|
variableDescriptor = (VariableDescriptor) descriptor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return variableDescriptor;
|
return variableDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<LocalVariableDescriptor> collectAllLocalVariables(Pseudocode pseudocode) {
|
private Set<VariableDescriptor> collectAllLocalVariables(Pseudocode pseudocode) {
|
||||||
final Set<LocalVariableDescriptor> localVariables = Sets.newHashSet();
|
final Set<VariableDescriptor> localVariables = Sets.newHashSet();
|
||||||
InstructionDataAnalyzer<Void> analyzer = new InstructionDataAnalyzer<Void>() {
|
JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy analyzeStrategy = new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() {
|
||||||
@Override
|
@Override
|
||||||
public void analyze(Instruction instruction, Map<Instruction, Void> dataMap) {
|
public void execute(Instruction instruction) {
|
||||||
LocalVariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction);
|
||||||
if (variableDescriptor != null) {
|
if (variableDescriptor != null) {
|
||||||
localVariables.add(variableDescriptor);
|
localVariables.add(variableDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
traverseAndAnalyzeInstructionGraph(pseudocode.getInstructions(), Collections.<Instruction, Void>emptyMap(), analyzer);
|
JetControlFlowGraphTraverser.traverseAndAnalyzeInstructionGraph(pseudocode, analyzeStrategy);
|
||||||
return localVariables;
|
return localVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D> void traverseAndAnalyzeInstructionGraph(Collection<Instruction> instructions, Map<Instruction, D> dataMap, InstructionDataAnalyzer<D> instructionDataAnalyzer) {
|
|
||||||
for (Instruction instruction : instructions) {
|
|
||||||
if (instruction instanceof LocalDeclarationInstruction) {
|
|
||||||
traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody().getInstructions(), dataMap, instructionDataAnalyzer);
|
|
||||||
}
|
|
||||||
instructionDataAnalyzer.analyze(instruction, dataMap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface InstructionsMergeHandler<D> {
|
|
||||||
D merge(Instruction instruction, Collection<D> incomingEdgesData);
|
|
||||||
}
|
|
||||||
|
|
||||||
interface InstructionDataAnalyzer<D> {
|
|
||||||
void analyze(Instruction instruction, Map<Instruction, D> dataMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class InitializationPoints {
|
private static class InitializationPoints {
|
||||||
private Set<JetElement> possiblePoints = Sets.newHashSet();
|
private Set<JetElement> possiblePoints = Sets.newHashSet();
|
||||||
private boolean canBeUninitialized;
|
private boolean canBeUninitialized;
|
||||||
|
|
||||||
public InitializationPoints() {
|
public InitializationPoints(boolean canBeUninitialized) {
|
||||||
canBeUninitialized = true;
|
this.canBeUninitialized = canBeUninitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InitializationPoints(JetElement element) {
|
public InitializationPoints(JetElement element) {
|
||||||
|
|||||||
@@ -145,6 +145,8 @@ public interface Errors {
|
|||||||
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME);
|
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME);
|
||||||
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> VAL_REASSIGNMENT = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME);
|
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> VAL_REASSIGNMENT = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME);
|
||||||
|
|
||||||
|
PsiElementOnlyDiagnosticFactory1<JetSimpleNameExpression, DeclarationDescriptor> FUNCTION_PARAMETERS_OF_INLINE_FUNCTION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Funciton parameters of inline funciton can only be invoked", NAME);
|
||||||
|
|
||||||
SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code");
|
SimpleDiagnosticFactory UNREACHABLE_CODE = SimpleDiagnosticFactory.create(ERROR, "Unreachable code");
|
||||||
|
|
||||||
SimpleDiagnosticFactory MANY_CLASS_OBJECTS = SimpleDiagnosticFactory.create(ERROR, "Only one class object is allowed per class");
|
SimpleDiagnosticFactory MANY_CLASS_OBJECTS = SimpleDiagnosticFactory.create(ERROR, "Only one class object is allowed per class");
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
|||||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -113,7 +114,12 @@ public class ControlFlowAnalyzer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!declaredLocally) {
|
if (!declaredLocally) {
|
||||||
flowInformationProvider.markUninitializedVariables(function.asElement());
|
flowInformationProvider.markUninitializedVariables(function.asElement(), functionDescriptor.getValueParameters());
|
||||||
|
|
||||||
|
if (((JetDeclaration) function).hasModifier(JetTokens.INLINE_KEYWORD)) {
|
||||||
|
//inline functions after M1
|
||||||
|
// flowInformationProvider.markNotOnlyInvokedFunctionVariables(function.asElement(), functionDescriptor.getValueParameters());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user