UNINITIALIZED_ENUM_ENTRY compiler warning introduced #KT-2349 Fixed

(cherry picked from commit 76ac6d1)
This commit is contained in:
Mikhail Glukhikh
2016-07-29 15:18:09 +03:00
committed by Mikhail Glukhikh
parent b7ed68db05
commit 35446037bb
20 changed files with 322 additions and 51 deletions
@@ -48,6 +48,8 @@ interface ControlFlowBuilder {
fun declareVariable(property: KtVariableDeclaration)
fun declareFunction(subroutine: KtElement, pseudocode: Pseudocode)
fun declareEnumEntry(enumEntry: KtEnumEntry)
// Labels
fun createUnboundLabel(): Label
@@ -200,6 +200,10 @@ abstract class ControlFlowBuilderAdapter : ControlFlowBuilder {
delegateBuilder.declareFunction(subroutine, pseudocode)
}
override fun declareEnumEntry(enumEntry: KtEnumEntry) {
delegateBuilder.declareEnumEntry(enumEntry)
}
override fun repeatPseudocode(startLabel: Label, finishLabel: Label) {
delegateBuilder.repeatPseudocode(startLabel, finishLabel)
}
@@ -52,6 +52,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getDispatchReceiverWithSmartCast
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.hasThisOrNoDispatchReceiver
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils.*
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
@@ -325,8 +326,12 @@ class ControlFlowInformationProvider private constructor(
variableDescriptor?.let { varWithUninitializedErrorGenerated.add(it) }
}
when (variableDescriptor) {
is ValueParameterDescriptor -> report(Errors.UNINITIALIZED_PARAMETER.on(element, variableDescriptor), ctxt)
is VariableDescriptor -> report(Errors.UNINITIALIZED_VARIABLE.on(element, variableDescriptor), ctxt)
is ValueParameterDescriptor ->
report(Errors.UNINITIALIZED_PARAMETER.on(element, variableDescriptor), ctxt)
is FakeCallableDescriptorForObject ->
report(Errors.UNINITIALIZED_ENUM_ENTRY.on(element, variableDescriptor.classDescriptor), ctxt)
is VariableDescriptor ->
report(Errors.UNINITIALIZED_VARIABLE.on(element, variableDescriptor), ctxt)
}
}
}
@@ -1267,6 +1267,24 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
}
override fun visitClass(klass: KtClass) {
if (klass.isEnum()) {
klass.declarations.forEach {
when (it) {
is KtEnumEntry -> {
val classDescriptor = trace[BindingContext.DECLARATION_TO_DESCRIPTOR, it]
if (classDescriptor is ClassDescriptor) {
builder.declareEnumEntry(it)
builder.write(it, it, createSyntheticValue(it, MagicKind.FAKE_INITIALIZER),
AccessTarget.Declaration(FakeCallableDescriptorForObject(classDescriptor)), emptyMap())
generateInstructions(it)
}
}
is KtObjectDeclaration -> {
generateInstructions(it)
}
}
}
}
if (klass.hasPrimaryConstructor()) {
processParameters(klass.getPrimaryConstructorParameters())
@@ -24,8 +24,11 @@ import org.jetbrains.kotlin.cfg.pseudocodeTraverser.Edges
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.collectData
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.traverse
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.calls.tower.getFakeDescriptorForObject
import java.util.ArrayList
import java.util.HashMap
@@ -74,19 +77,15 @@ class PseudocodeVariableDataCollector(
pseudocode.traverse(TraversalOrder.FORWARD, { instruction ->
if (instruction is VariableDeclarationInstruction) {
val variableDeclarationElement = instruction.variableDeclarationElement
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement)
if (descriptor != null) {
// TODO: investigate why tests fail without this eager computation here
descriptor.toString()
assert(descriptor is VariableDescriptor) {
"Variable descriptor should correspond to the instruction for ${instruction.element.text}.\n" +
"Descriptor: $descriptor"
}
blockScopeVariableInfo.registerVariableDeclaredInScope(
descriptor as VariableDescriptor, instruction.blockScope
)
}
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement) ?: return@traverse
// TODO: investigate why tests fail without this eager computation here
// TODO: https://youtrack.jetbrains.com/issue/KT-13354
descriptor.toString()
val variableDescriptor = BindingContextUtils.variableDescriptorForDeclaration(descriptor)
?: throw AssertionError("Variable or class descriptor should correspond to " +
"the instruction for ${instruction.element.text}.\n" +
"Descriptor: $descriptor")
blockScopeVariableInfo.registerVariableDeclaredInScope(variableDescriptor, instruction.blockScope)
}
})
return blockScopeVariableInfo
@@ -25,9 +25,15 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.VariableDeclarationInstruction
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.Edges
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.BindingContextUtils.variableDescriptorForDeclaration
import org.jetbrains.kotlin.resolve.calls.tower.getFakeDescriptorForObject
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import java.util.Collections
class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingContext: BindingContext) {
@@ -75,9 +81,8 @@ class PseudocodeVariablesData(val pseudocode: Pseudocode, private val bindingCon
if (instruction is VariableDeclarationInstruction) {
val variableDeclarationElement = instruction.variableDeclarationElement
val descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, variableDeclarationElement)
if (descriptor != null) {
assert(descriptor is VariableDescriptor)
declaredVariables.add(descriptor as VariableDescriptor?)
variableDescriptorForDeclaration(descriptor)?.let {
declaredVariables.add(it)
}
}
}
@@ -274,6 +274,10 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
add(LocalFunctionDeclarationInstruction(subroutine, pseudocode, currentScope))
}
override fun declareEnumEntry(enumEntry: KtEnumEntry) {
add(VariableDeclarationInstruction(enumEntry, currentScope))
}
override fun loadUnit(expression: KtExpression) {
add(LoadUnitValueInstruction(expression, currentScope))
}
@@ -24,13 +24,16 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionImpl
import org.jetbrains.kotlin.psi.KtEnumEntry
class VariableDeclarationInstruction(
element: KtDeclaration,
blockScope: BlockScope
) : InstructionWithNext(element, blockScope) {
init {
assert(element is KtVariableDeclaration || element is KtParameter) { "Invalid element: ${render(element)}}" }
assert(element is KtVariableDeclaration || element is KtParameter || element is KtEnumEntry) {
"Invalid element: ${render(element)}}"
}
}
val variableDeclarationElement: KtDeclaration
@@ -171,9 +171,9 @@ fun getExpectedTypePredicate(
else {
val expectedType = when (accessTarget) {
is AccessTarget.Call ->
(accessTarget.resolvedCall.getResultingDescriptor() as? VariableDescriptor)?.getType()
(accessTarget.resolvedCall.resultingDescriptor as? VariableDescriptor)?.type
is AccessTarget.Declaration ->
accessTarget.descriptor.getType()
accessTarget.descriptor.type
else ->
null
}
@@ -239,7 +239,7 @@ fun getExpectedTypePredicate(
fun Instruction.getPrimaryDeclarationDescriptorIfAny(bindingContext: BindingContext): DeclarationDescriptor? {
return when (this) {
is CallInstruction -> return resolvedCall.getResultingDescriptor()
is CallInstruction -> return resolvedCall.resultingDescriptor
else -> PseudocodeUtil.extractVariableDescriptorIfAny(this, false, bindingContext)
}
}
@@ -644,6 +644,7 @@ public interface Errors {
DiagnosticFactory1<KtSimpleNameExpression, VariableDescriptor> UNINITIALIZED_VARIABLE = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtSimpleNameExpression, ValueParameterDescriptor> UNINITIALIZED_PARAMETER = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtSimpleNameExpression, ClassDescriptor> UNINITIALIZED_ENUM_ENTRY = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtNamedDeclaration, VariableDescriptor> UNUSED_VARIABLE = DiagnosticFactory1.create(WARNING, DECLARATION_NAME);
DiagnosticFactory1<KtParameter, VariableDescriptor> UNUSED_PARAMETER = DiagnosticFactory1.create(WARNING, DECLARATION_NAME);
@@ -264,6 +264,7 @@ public class DefaultErrorMessages {
MAP.put(UNINITIALIZED_VARIABLE, "Variable ''{0}'' must be initialized", NAME);
MAP.put(UNINITIALIZED_PARAMETER, "Parameter ''{0}'' is uninitialized here", NAME);
MAP.put(UNINITIALIZED_ENUM_ENTRY, "Enum entry ''{0}'' is uninitialized here", NAME);
MAP.put(UNUSED_VARIABLE, "Variable ''{0}'' is never used", NAME);
MAP.put(UNUSED_PARAMETER, "Parameter ''{0}'' is never used", NAME);
MAP.put(ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE, "Variable ''{0}'' is assigned but never accessed", NAME);
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
import org.jetbrains.kotlin.resolve.calls.tower.TowerLevelsKt;
import org.jetbrains.kotlin.resolve.diagnostics.MutableDiagnosticsWithSuppression;
import org.jetbrains.kotlin.types.KotlinType;
import org.jetbrains.kotlin.types.TypeUtils;
@@ -56,10 +57,21 @@ public class BindingContextUtils {
return (VariableDescriptor) resolvedCall.getResultingDescriptor();
}
@Nullable
public static VariableDescriptor variableDescriptorForDeclaration(@Nullable DeclarationDescriptor descriptor) {
if (descriptor instanceof VariableDescriptor)
return (VariableDescriptor) descriptor;
if (descriptor instanceof ClassDescriptor) {
return TowerLevelsKt.getFakeDescriptorForObject((ClassDescriptor) descriptor);
}
return null;
}
@Nullable
public static VariableDescriptor extractVariableDescriptorIfAny(@NotNull BindingContext bindingContext, @Nullable KtElement element, boolean onlyReference) {
DeclarationDescriptor descriptor = null;
if (!onlyReference && (element instanceof KtVariableDeclaration || element instanceof KtParameter)) {
if (!onlyReference &&
(element instanceof KtVariableDeclaration || element instanceof KtParameter || element instanceof KtEnumEntry)) {
descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
}
else if (element instanceof KtSimpleNameExpression) {
@@ -68,10 +80,7 @@ public class BindingContextUtils {
else if (element instanceof KtQualifiedExpression) {
descriptor = extractVariableDescriptorIfAny(bindingContext, ((KtQualifiedExpression) element).getSelectorExpression(), onlyReference);
}
if (descriptor instanceof VariableDescriptor) {
return (VariableDescriptor) descriptor;
}
return null;
return variableDescriptorForDeclaration(descriptor);
}
public static void recordFunctionDeclarationToDescriptor(@NotNull BindingTrace trace,