Drop traits with required classes
#KT-4771 Rejected
This commit is contained in:
+14
-13
@@ -16,17 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.cfg.pseudocode.instructions.eval
|
||||
|
||||
import org.jetbrains.kotlin.psi.JetElement
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValueFactory
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.TypePredicate
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionWithNext
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.LexicalScope
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.TypePredicate
|
||||
import org.jetbrains.kotlin.psi.JetElement
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
|
||||
public abstract class OperationInstruction protected constructor(
|
||||
element: JetElement,
|
||||
@@ -53,11 +53,6 @@ public abstract class OperationInstruction protected constructor(
|
||||
}
|
||||
}
|
||||
|
||||
trait StrictlyValuedOperationInstruction: OperationInstruction {
|
||||
override val outputValue: PseudoValue
|
||||
get() = resultValue!!
|
||||
}
|
||||
|
||||
public class CallInstruction private constructor(
|
||||
element: JetElement,
|
||||
lexicalScope: LexicalScope,
|
||||
@@ -103,9 +98,12 @@ public class MagicInstruction(
|
||||
inputValues: List<PseudoValue>,
|
||||
val expectedTypes: Map<PseudoValue, TypePredicate>,
|
||||
val kind: MagicKind
|
||||
) : OperationInstruction(element, lexicalScope, inputValues), StrictlyValuedOperationInstruction {
|
||||
) : OperationInstruction(element, lexicalScope, inputValues) {
|
||||
public val synthetic: Boolean get() = outputValue.element == null
|
||||
|
||||
override val outputValue: PseudoValue
|
||||
get() = resultValue!!
|
||||
|
||||
override fun accept(visitor: InstructionVisitor) = visitor.visitMagic(this)
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitMagic(this)
|
||||
@@ -156,7 +154,10 @@ class MergeInstruction private constructor(
|
||||
element: JetElement,
|
||||
lexicalScope: LexicalScope,
|
||||
inputValues: List<PseudoValue>
|
||||
): OperationInstruction(element, lexicalScope, inputValues), StrictlyValuedOperationInstruction {
|
||||
): OperationInstruction(element, lexicalScope, inputValues) {
|
||||
override val outputValue: PseudoValue
|
||||
get() = resultValue!!
|
||||
|
||||
override fun accept(visitor: InstructionVisitor) = visitor.visitMerge(this)
|
||||
|
||||
override fun <R> accept(visitor: InstructionVisitorWithResult<R>): R = visitor.visitMerge(this)
|
||||
|
||||
@@ -192,10 +192,7 @@ public interface Errors {
|
||||
|
||||
DiagnosticFactory0<JetDelegatorByExpressionSpecifier> DELEGATION_IN_TRAIT = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<PsiElement> TRAIT_WITH_SUPERCLASS = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory2<JetNamedDeclaration, ClassDescriptor, ClassDescriptor> UNMET_TRAIT_REQUIREMENT =
|
||||
DiagnosticFactory2.create(ERROR, PositioningStrategies.DECLARATION_NAME);
|
||||
DiagnosticFactory0<PsiElement> TRAIT_WITH_SUPERCLASS = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
// Enum-specific
|
||||
|
||||
|
||||
+1
-2
@@ -296,7 +296,6 @@ public class DefaultErrorMessages {
|
||||
MAP.put(DELEGATION_IN_TRAIT, "Interfaces cannot use delegation");
|
||||
MAP.put(DELEGATION_NOT_TO_TRAIT, "Only interfaces can be delegated to");
|
||||
MAP.put(DEPRECATED_TRAIT_KEYWORD, "'trait' keyword is deprecated, use 'interface' instead");
|
||||
MAP.put(UNMET_TRAIT_REQUIREMENT, "Super interface ''{0}'' requires subclasses to extend ''{1}''", NAME, NAME);
|
||||
MAP.put(NO_CONSTRUCTOR, "This class does not have a constructor");
|
||||
MAP.put(NOT_A_CLASS, "Not a class");
|
||||
MAP.put(ILLEGAL_ESCAPE_SEQUENCE, "Illegal escape sequence");
|
||||
@@ -428,7 +427,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(SUPERTYPE_INITIALIZED_IN_TRAIT, "Interfaces cannot initialize supertypes");
|
||||
MAP.put(CLASS_IN_SUPERTYPE_FOR_ENUM, "Enum class cannot inherit from classes");
|
||||
MAP.put(CONSTRUCTOR_IN_TRAIT, "An interface may not have a constructor");
|
||||
MAP.put(TRAIT_WITH_SUPERCLASS, "Specifying a required base class for interface implementations is deprecated");
|
||||
MAP.put(TRAIT_WITH_SUPERCLASS, "An interface cannot inherit from a class");
|
||||
MAP.put(SUPERTYPE_APPEARS_TWICE, "A supertype appears twice");
|
||||
MAP.put(FINAL_SUPERTYPE, "This type is final, so it cannot be inherited from");
|
||||
MAP.put(SINGLETON_IN_SUPERTYPE, "Cannot inherit from a singleton");
|
||||
|
||||
@@ -426,6 +426,8 @@ public class BodyResolver {
|
||||
JetTypeReference typeReference = entry.getKey();
|
||||
JetType supertype = entry.getValue();
|
||||
|
||||
boolean addSupertype = true;
|
||||
|
||||
ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
|
||||
if (classDescriptor != null) {
|
||||
if (ErrorUtils.isError(classDescriptor)) continue;
|
||||
@@ -433,11 +435,14 @@ public class BodyResolver {
|
||||
if (classDescriptor.getKind() != ClassKind.INTERFACE) {
|
||||
if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) {
|
||||
trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference));
|
||||
addSupertype = false;
|
||||
}
|
||||
else if (supertypeOwner.getKind() == ClassKind.INTERFACE &&
|
||||
!classAppeared && !TypesPackage.isDynamic(supertype) /* avoid duplicate diagnostics */) {
|
||||
trace.report(TRAIT_WITH_SUPERCLASS.on(typeReference));
|
||||
addSupertype = false;
|
||||
}
|
||||
|
||||
if (classAppeared) {
|
||||
trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference));
|
||||
}
|
||||
@@ -451,7 +456,7 @@ public class BodyResolver {
|
||||
}
|
||||
|
||||
TypeConstructor constructor = supertype.getConstructor();
|
||||
if (!typeConstructors.add(constructor)) {
|
||||
if (addSupertype && !typeConstructors.add(constructor)) {
|
||||
trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,16 +21,15 @@ import com.google.common.collect.Multimap
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.CONSTRUCTOR_IN_OBJECT
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.CONSTRUCTOR_IN_TRAIT
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.MANY_COMPANION_OBJECTS
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.CONSTRUCTOR_IN_OBJECT
|
||||
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.lazy.*
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
|
||||
import org.jetbrains.kotlin.resolve.resolveUtil.checkTraitRequirements
|
||||
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker
|
||||
import java.util.ArrayList
|
||||
import javax.inject.Inject
|
||||
@@ -244,8 +243,6 @@ public class LazyTopDownAnalyzer {
|
||||
declarationResolver!!.checkRedeclarationsInPackages(topLevelDescriptorProvider!!, topLevelFqNames)
|
||||
declarationResolver!!.checkRedeclarations(c)
|
||||
|
||||
checkTraitRequirements(c.getDeclaredClasses(), trace!!)
|
||||
|
||||
overrideResolver!!.check(c)
|
||||
|
||||
varianceChecker!!.check(c)
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.resolveUtil
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.JetClassOrObject
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassOrAny
|
||||
|
||||
fun checkTraitRequirements(c: Map<JetClassOrObject, ClassDescriptorWithResolutionScopes>, trace: BindingTrace) {
|
||||
for ((classOrObject, descriptor) in c.entrySet()) {
|
||||
if (DescriptorUtils.isTrait(descriptor)) continue
|
||||
|
||||
val satisfiedRequirements = getSuperClassesReachableByClassInheritance(descriptor)
|
||||
for (superTrait in getAllSuperTraits(descriptor)) {
|
||||
for (traitSupertype in superTrait.getDefaultType().getConstructor().getSupertypes()) {
|
||||
val traitSuperClass = traitSupertype.getConstructor().getDeclarationDescriptor()
|
||||
if (DescriptorUtils.isClass(traitSuperClass) && traitSuperClass !in satisfiedRequirements) {
|
||||
trace.report(Errors.UNMET_TRAIT_REQUIREMENT.on(classOrObject, superTrait, traitSuperClass as ClassDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAllSuperTraits(descriptor: ClassDescriptor): List<ClassDescriptor> {
|
||||
@suppress("UNCHECKED_CAST")
|
||||
return TypeUtils.getAllSupertypes(descriptor.getDefaultType())
|
||||
.map { supertype -> supertype.getConstructor().getDeclarationDescriptor() }
|
||||
.filter { superClass -> DescriptorUtils.isTrait(superClass) } as List<ClassDescriptor>
|
||||
}
|
||||
|
||||
private fun getSuperClassesReachableByClassInheritance(
|
||||
descriptor: ClassDescriptor,
|
||||
result: MutableSet<ClassDescriptor> = hashSetOf()
|
||||
): Set<ClassDescriptor> {
|
||||
val superClass = descriptor.getSuperClassOrAny()
|
||||
result.add(superClass)
|
||||
if (!KotlinBuiltIns.isAny(superClass)) {
|
||||
getSuperClassesReachableByClassInheritance(superClass, result)
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user