check package declaration in a file

to have the right properties initialization order
not to report errors if isDeclaredLocally (only recordInitializedVariables)
This commit is contained in:
Svetlana Isakova
2012-12-18 15:52:39 +04:00
parent 57518c1200
commit 11bc01795f
4 changed files with 40 additions and 19 deletions
@@ -188,7 +188,7 @@ public class JetFlowInformationProvider {
////////////////////////////////////////////////////////////////////////////////
// Uninitialized variables analysis
public void markUninitializedVariables(final boolean processLocalDeclaration) {
public void markUninitializedVariables() {
final Collection<VariableDescriptor> varWithUninitializedErrorGenerated = Sets.newHashSet();
final Collection<VariableDescriptor> varWithValReassignErrorGenerated = Sets.newHashSet();
final boolean processClassOrObject = subroutine instanceof JetClassOrObject;
@@ -218,7 +218,7 @@ public class JetFlowInformationProvider {
JetElement element = ((WriteValueInstruction) instruction).getlValue();
boolean error = checkBackingField(ctxt, element);
if (!(element instanceof JetExpression)) return;
if (!error && !processLocalDeclaration) { // error has been generated before, while processing outer function of this local declaration
if (!error) {
error = checkValReassignment(ctxt, (JetExpression) element, varWithValReassignErrorGenerated);
}
if (!error && processClassOrObject) {
@@ -229,8 +229,11 @@ public class JetFlowInformationProvider {
}
}
});
}
public void recordInitializedVariables() {
Pseudocode pseudocode = pseudocodeVariablesData.getPseudocode();
Map<Instruction, Edges<Map<VariableDescriptor,VariableInitState>>> initializers = pseudocodeVariablesData.getVariableInitializers();
recordInitializedVariables(pseudocode, initializers);
for (LocalDeclarationInstruction instruction : pseudocode.getLocalDeclarations()) {
recordInitializedVariables(instruction.getBody(), initializers);
@@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.resolve;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.cfg.JetFlowInformationProvider;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor;
@@ -26,6 +25,7 @@ import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.types.JetType;
import javax.inject.Inject;
import java.util.List;
import java.util.Map;
import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
@@ -48,13 +48,16 @@ public class ControlFlowAnalyzer {
}
public void process(@NotNull BodiesResolveContext bodiesResolveContext) {
for (JetFile file : bodiesResolveContext.getFiles()) {
checkDeclarationContainer(file);
}
for (JetClass aClass : bodiesResolveContext.getClasses().keySet()) {
if (!bodiesResolveContext.completeAnalysisNeeded(aClass)) continue;
checkClassOrObject(aClass);
checkDeclarationContainer(aClass);
}
for (JetObjectDeclaration objectDeclaration : bodiesResolveContext.getObjects().keySet()) {
if (!bodiesResolveContext.completeAnalysisNeeded(objectDeclaration)) continue;
checkClassOrObject(objectDeclaration);
checkDeclarationContainer(objectDeclaration);
}
for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : bodiesResolveContext.getFunctions().entrySet()) {
JetNamedFunction function = entry.getKey();
@@ -73,10 +76,15 @@ public class ControlFlowAnalyzer {
}
}
private void checkClassOrObject(JetClassOrObject klass) {
// A pseudocode of class initialization corresponds to a class
JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider(klass, trace);
flowInformationProvider.markUninitializedVariables(topDownAnalysisParameters.isDeclaredLocally());
private void checkDeclarationContainer(JetDeclarationContainer declarationContainer) {
// A pseudocode of class/object initialization corresponds to a class/object
// or initialization of properties corresponds to a package declared in a file
JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetElement) declarationContainer, trace);
flowInformationProvider.recordInitializedVariables();
if (topDownAnalysisParameters.isDeclaredLocally()) return;
flowInformationProvider.markUninitializedVariables();
}
private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) {
@@ -87,13 +95,6 @@ public class ControlFlowAnalyzer {
assert accessorDescriptor != null;
checkFunction(accessor, accessorDescriptor.getReturnType());
}
if (property.getInitializer() != null && propertyDescriptor.getContainingDeclaration() instanceof NamespaceDescriptor) {
// check initializer's pseudocode for uninitialized values
// initializers of properties inside classes/objects are checked in 'checkClassOrObject',
// because class/object may have anonymous initialization blocks that affect analysis
JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider(property, trace);
flowInformationProvider.markUninitializedVariables(false);
}
}
private void checkFunction(JetDeclarationWithBody function, final @NotNull JetType expectedReturnType) {
@@ -103,11 +104,19 @@ public class ControlFlowAnalyzer {
if (bodyExpression == null) return;
JetFlowInformationProvider flowInformationProvider = new JetFlowInformationProvider((JetDeclaration) function, trace);
boolean isPropertyAccessor = function instanceof JetPropertyAccessor;
if (!isPropertyAccessor) {
flowInformationProvider.recordInitializedVariables();
}
if (topDownAnalysisParameters.isDeclaredLocally()) return;
flowInformationProvider.checkDefiniteReturn(expectedReturnType);
// Property accessor is checked through initialization of a class check (at 'checkClassOrObject')
boolean isPropertyAccessor = function instanceof JetPropertyAccessor;
flowInformationProvider.markUninitializedVariables(topDownAnalysisParameters.isDeclaredLocally() || isPropertyAccessor);
if (!isPropertyAccessor) {
// Property accessor is checked through initialization of a class/object or package properties (at 'checkDeclarationContainer')
flowInformationProvider.markUninitializedVariables();
}
flowInformationProvider.markUnusedVariables();
@@ -0,0 +1,4 @@
package a
val a : Int = <!UNINITIALIZED_VARIABLE!>b<!>
val b : Int = a
@@ -964,6 +964,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/kt897.kt");
}
@TestMetadata("propertiesOrderInPackage.kt")
public void testPropertiesOrderInPackage() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/propertiesOrderInPackage.kt");
}
@TestMetadata("uninitializedInLocalDeclarations.kt")
public void testUninitializedInLocalDeclarations() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/uninitializedInLocalDeclarations.kt");