KT-13961 REDECLARATION not reported on private-in-file 'foo' vs public 'foo' in different file

Private-in-file declarations conflict with public overload-equivalent declarations
in other files in the same package.

Move functions for grouping possible redeclarations to OverloadResolver
(since they are used only there).

Refactor redeclarations / conflicting overloads reporting.
This commit is contained in:
Dmitry Petrov
2016-09-21 18:12:24 +03:00
parent 0120085443
commit 06101dba52
42 changed files with 293 additions and 297 deletions
@@ -65,7 +65,10 @@ public interface Errors {
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
DiagnosticFactory1<PsiElement, String> REDECLARATION = DiagnosticFactory1.create(ERROR, FOR_REDECLARATION);
DiagnosticFactory1<PsiElement, Collection<DeclarationDescriptor>> REDECLARATION =
DiagnosticFactory1.create(ERROR, FOR_REDECLARATION);
DiagnosticFactory1<PsiElement, String> PACKAGE_OR_CLASSIFIER_REDECLARATION =
DiagnosticFactory1.create(ERROR, FOR_REDECLARATION);
DiagnosticFactory1<KtReferenceExpression, KtReferenceExpression> UNRESOLVED_REFERENCE =
DiagnosticFactory1.create(ERROR, FOR_UNRESOLVED_REFERENCE);
@@ -315,8 +318,8 @@ public interface Errors {
// Members
DiagnosticFactory2<PsiElement, CallableMemberDescriptor, DeclarationDescriptor> CONFLICTING_OVERLOADS =
DiagnosticFactory2.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
DiagnosticFactory1<PsiElement, Collection<DeclarationDescriptor>> CONFLICTING_OVERLOADS =
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
DiagnosticFactory0<KtNamedDeclaration> NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticFactory0.create(WARNING, modifierSetPosition(
KtTokens.OPEN_KEYWORD));
@@ -17,14 +17,16 @@
package org.jetbrains.kotlin.diagnostics
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.context.CallPosition
@@ -139,3 +141,22 @@ fun ResolutionContext<*>.reportTypeMismatchDueToScalaLikeNamedFunctionSyntax(
private fun isScalaLikeEqualsBlock(expression: KtElement): Boolean =
expression is KtLambdaExpression &&
expression.parent.let { it is KtNamedFunction && it.equalsToken != null }
inline fun reportOnDeclaration(trace: BindingTrace, descriptor: DeclarationDescriptor, what: (PsiElement) -> Diagnostic) {
DescriptorToSourceUtils.descriptorToDeclaration(descriptor)?.let { psiElement ->
trace.report(what(psiElement))
}
}
inline fun reportOnDeclarationOrFail(trace: BindingTrace, descriptor: DeclarationDescriptor, what: (PsiElement) -> Diagnostic) {
DescriptorToSourceUtils.descriptorToDeclaration(descriptor)?.let { psiElement ->
trace.report(what(psiElement))
} ?: throw AssertionError("No declaration for $descriptor")
}
inline fun <reified T : KtDeclaration> reportOnDeclarationAs(trace: BindingTrace, descriptor: DeclarationDescriptor, what: (T) -> Diagnostic) {
DescriptorToSourceUtils.descriptorToDeclaration(descriptor)?.let { psiElement ->
(psiElement as? T)?.let {
trace.report(what(it))
} ?: throw AssertionError("Declaration for $descriptor is expected to be ${T::class.simpleName}, actual declaration: $psiElement")
} ?: throw AssertionError("No declaration for $descriptor")
}
@@ -110,7 +110,9 @@ public class DefaultErrorMessages {
MAP.put(INACCESSIBLE_TYPE, "Type {0} is inaccessible in this context due to: {1}", RENDER_TYPE, RENDER_COLLECTION_OF_TYPES);
MAP.put(REDECLARATION, "Redeclaration: {0}", STRING);
MAP.put(REDECLARATION, "Conflicting declarations: {0}", commaSeparated(COMPACT_WITH_MODIFIERS));
MAP.put(PACKAGE_OR_CLASSIFIER_REDECLARATION, "Redeclaration: {0}", STRING);
MAP.put(NAME_SHADOWING, "Name shadowed: {0}", STRING);
MAP.put(ACCESSOR_PARAMETER_NAME_SHADOWING, "Accessor parameter name 'field' is shadowed by backing field variable");
@@ -631,8 +633,7 @@ public class DefaultErrorMessages {
MAP.put(MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED, "{0} must override {1} because it inherits multiple interface methods of it",
RENDER_CLASS_OR_OBJECT, FQ_NAMES_IN_TYPES);
MAP.put(CONFLICTING_OVERLOADS, "''{0}'' conflicts with another declaration in {1}", COMPACT_WITH_MODIFIERS,
DECLARATION_NAME_WITH_KIND);
MAP.put(CONFLICTING_OVERLOADS, "Conflicting overloads: {0}", commaSeparated(FQ_NAMES_IN_TYPES));
MAP.put(FUNCTION_EXPECTED, "Expression ''{0}''{1} cannot be invoked as a function. " +
"The function ''" + OperatorNameConventions.INVOKE.asString() + "()'' is not found",
@@ -18,14 +18,13 @@ package org.jetbrains.kotlin.resolve
import com.google.common.collect.HashMultimap
import com.google.common.collect.Multimap
import com.google.common.collect.Sets
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Errors.REDECLARATION
import org.jetbrains.kotlin.diagnostics.reportOnDeclaration
import org.jetbrains.kotlin.diagnostics.reportOnDeclarationOrFail
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
@@ -60,40 +59,19 @@ class DeclarationResolver(
}
}
reportRedeclarations(descriptorMap)
reportRedeclarationsWithClassifiers(descriptorMap)
}
}
private fun reportRedeclarations(descriptorMap: Multimap<Name, DeclarationDescriptor>) {
val redeclarations = Sets.newHashSet<Pair<PsiElement, Name>>()
private fun reportRedeclarationsWithClassifiers(descriptorMap: Multimap<Name, DeclarationDescriptor>) {
for (name in descriptorMap.keySet()) {
val descriptors = descriptorMap[name]
if (descriptors.size <= 1) {
continue
}
// We mustn't compare PropertyDescriptor with PropertyDescriptor because we do this at OverloadResolver
for (descriptor in descriptors) {
if (descriptor is ClassifierDescriptor) {
for (descriptor2 in descriptors) {
if (descriptor === descriptor2) {
continue
}
DescriptorToSourceUtils.getSourceFromDescriptor(descriptor)?.let {
redeclarations.add(Pair(it, descriptor.getName()))
}
if (descriptor2 is PropertyDescriptor) {
DescriptorToSourceUtils.descriptorToDeclaration(descriptor2)?.let {
redeclarations.add(Pair(it, descriptor2.getName()))
}
}
}
if (descriptors.size > 1 && descriptors.any { it is ClassifierDescriptor }) {
for (descriptor in descriptors) {
reportOnDeclaration(trace, descriptor) { REDECLARATION.on(it, descriptors) }
}
}
}
for ((first, second) in redeclarations) {
trace.report(REDECLARATION.on(first, second.asString()))
}
}
fun checkRedeclarationsInPackages(topLevelDescriptorProvider: TopLevelDescriptorProvider, topLevelFqNames: Multimap<FqName, KtElement>) {
@@ -107,7 +85,7 @@ class DeclarationResolver(
val reportAt =
if (declarationOrPackageDirective is KtPackageDirective) declarationOrPackageDirective.getNameIdentifier()
else declarationOrPackageDirective
trace.report(Errors.REDECLARATION.on(reportAt!!, fqName.shortName().asString()))
trace.report(Errors.PACKAGE_OR_CLASSIFIER_REDECLARATION.on(reportAt!!, fqName.shortName().asString()))
}
}
}
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import java.util.*
class OverloadChecker(val specificityComparator: TypeSpecificityComparator) {
/**
@@ -98,118 +99,4 @@ class OverloadChecker(val specificityComparator: TypeSpecificityComparator) {
error("Unexpected declaration kind: $a")
}
fun groupModulePackageMembersByFqName(
c: BodiesResolveContext,
overloadFilter: OverloadFilter
): MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot> {
val packageMembersByName = MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot>()
collectModulePackageMembersWithSameName(
packageMembersByName,
c.functions.values + c.declaredClasses.values + c.typeAliases.values,
overloadFilter
) {
scope, name ->
val functions = scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
when (classifier) {
is ClassDescriptor ->
if (!classifier.kind.isSingleton)
functions + classifier.constructors
else
functions
is TypeAliasDescriptor ->
functions + classifier.getTypeAliasConstructors()
else ->
functions
}
}
collectModulePackageMembersWithSameName(packageMembersByName, c.properties.values, overloadFilter) {
scope, name ->
val variables = scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
variables + classifier.singletonOrEmptyList()
}
return packageMembersByName
}
private inline fun collectModulePackageMembersWithSameName(
packageMembersByName: MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot>,
interestingDescriptors: Collection<DeclarationDescriptor>,
overloadFilter: OverloadFilter,
getMembersByName: (MemberScope, Name) -> Collection<DeclarationDescriptorNonRoot>
) {
val observedFQNs = hashSetOf<FqNameUnsafe>()
for (descriptor in interestingDescriptors) {
if (descriptor.containingDeclaration !is PackageFragmentDescriptor) continue
val descriptorFQN = DescriptorUtils.getFqName(descriptor)
if (observedFQNs.contains(descriptorFQN)) continue
observedFQNs.add(descriptorFQN)
val packageMembersWithSameName = getModulePackageMembersWithSameName(descriptor, overloadFilter, getMembersByName)
packageMembersByName.putValues(descriptorFQN, packageMembersWithSameName)
}
}
private inline fun getModulePackageMembersWithSameName(
descriptor: DeclarationDescriptor,
overloadFilter: OverloadFilter,
getMembersByName: (MemberScope, Name) -> Collection<DeclarationDescriptorNonRoot>
): Collection<DeclarationDescriptorNonRoot> {
val containingPackage = descriptor.containingDeclaration
if (containingPackage !is PackageFragmentDescriptor) {
throw AssertionError("$descriptor is not a top-level package member")
}
val containingModule = DescriptorUtils.getContainingModuleOrNull(descriptor) ?:
return when (descriptor) {
is CallableMemberDescriptor -> listOf(descriptor)
is ClassDescriptor -> descriptor.constructors
else -> throw AssertionError("Unexpected descriptor kind: $descriptor")
}
val containingPackageScope = containingModule.getPackage(containingPackage.fqName).memberScope
val possibleOverloads =
getMembersByName(containingPackageScope, descriptor.name).filter {
// NB memberScope for PackageViewDescriptor includes module dependencies
DescriptorUtils.getContainingModule(it) == containingModule
}
return overloadFilter.filterPackageMemberOverloads(possibleOverloads)
}
private fun DeclarationDescriptor.isPrivate() =
this is DeclarationDescriptorWithVisibility &&
Visibilities.isPrivate(this.visibility)
fun getPossibleRedeclarationGroups(
members: Collection<DeclarationDescriptorNonRoot>
): Collection<Collection<DeclarationDescriptorNonRoot>> {
val result = arrayListOf<Collection<DeclarationDescriptorNonRoot>>()
val nonPrivates = members.filter { !it.isPrivate() }
if (nonPrivates.size > 1) {
result.add(nonPrivates)
}
val bySourceFile = MultiMap.createSmart<SourceFile, DeclarationDescriptorNonRoot>()
for (member in members) {
val sourceFile = DescriptorUtils.getContainingSourceFile(member)
if (sourceFile != SourceFile.NO_SOURCE_FILE) {
bySourceFile.putValue(sourceFile, member)
}
}
for ((sourceFile, membersInFile) in bySourceFile.entrySet()) {
// File member groups are interesting in redeclaration check if at least one file member is private.
if (membersInFile.size > 1 && membersInFile.any { it.isPrivate() }) {
result.add(membersInFile)
}
}
return result
}
}
@@ -19,11 +19,15 @@ package org.jetbrains.kotlin.resolve
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.reportOnDeclaration
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.calls.tower.getTypeAliasConstructors
import org.jetbrains.kotlin.utils.addToStdlib.check
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.utils.singletonOrEmptyList
import java.util.*
class OverloadResolver(
private val trace: BindingTrace,
@@ -73,13 +77,96 @@ class OverloadResolver(
}
private fun checkOverloadsInPackages(c: BodiesResolveContext) {
val membersByName = overloadChecker.groupModulePackageMembersByFqName(c, overloadFilter)
val membersByName = groupModulePackageMembersByFqName(c, overloadFilter)
for (e in membersByName.entrySet()) {
checkOverloadsInPackage(e.value)
}
}
private fun groupModulePackageMembersByFqName(
c: BodiesResolveContext,
overloadFilter: OverloadFilter
): MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot> {
val packageMembersByName = MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot>()
collectModulePackageMembersWithSameName(
packageMembersByName,
c.functions.values + c.declaredClasses.values + c.typeAliases.values,
overloadFilter
) {
scope, name ->
val functions = scope.getContributedFunctions(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
when (classifier) {
is ClassDescriptor ->
if (!classifier.kind.isSingleton)
functions + classifier.constructors
else
functions
is TypeAliasDescriptor ->
functions + classifier.getTypeAliasConstructors()
else ->
functions
}
}
collectModulePackageMembersWithSameName(packageMembersByName, c.properties.values, overloadFilter) {
scope, name ->
val variables = scope.getContributedVariables(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
val classifier = scope.getContributedClassifier(name, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
variables + classifier.singletonOrEmptyList()
}
return packageMembersByName
}
private inline fun collectModulePackageMembersWithSameName(
packageMembersByName: MultiMap<FqNameUnsafe, DeclarationDescriptorNonRoot>,
interestingDescriptors: Collection<DeclarationDescriptor>,
overloadFilter: OverloadFilter,
getMembersByName: (MemberScope, Name) -> Collection<DeclarationDescriptorNonRoot>
) {
val observedFQNs = hashSetOf<FqNameUnsafe>()
for (descriptor in interestingDescriptors) {
if (descriptor.containingDeclaration !is PackageFragmentDescriptor) continue
val descriptorFQN = DescriptorUtils.getFqName(descriptor)
if (observedFQNs.contains(descriptorFQN)) continue
observedFQNs.add(descriptorFQN)
val packageMembersWithSameName = getModulePackageMembersWithSameName(descriptor, overloadFilter, getMembersByName)
packageMembersByName.putValues(descriptorFQN, packageMembersWithSameName)
}
}
private inline fun getModulePackageMembersWithSameName(
descriptor: DeclarationDescriptor,
overloadFilter: OverloadFilter,
getMembersByName: (MemberScope, Name) -> Collection<DeclarationDescriptorNonRoot>
): Collection<DeclarationDescriptorNonRoot> {
val containingPackage = descriptor.containingDeclaration
if (containingPackage !is PackageFragmentDescriptor) {
throw AssertionError("$descriptor is not a top-level package member")
}
val containingModule = DescriptorUtils.getContainingModuleOrNull(descriptor) ?:
return when (descriptor) {
is CallableMemberDescriptor -> listOf(descriptor)
is ClassDescriptor -> descriptor.constructors
else -> throw AssertionError("Unexpected descriptor kind: $descriptor")
}
val containingPackageScope = containingModule.getPackage(containingPackage.fqName).memberScope
val possibleOverloads =
getMembersByName(containingPackageScope, descriptor.name).filter {
// NB memberScope for PackageViewDescriptor includes module dependencies
DescriptorUtils.getContainingModule(it) == containingModule
}
return overloadFilter.filterPackageMemberOverloads(possibleOverloads)
}
private fun checkOverloadsInClass(
classDescriptor: ClassDescriptorWithResolutionScopes,
nestedClassConstructors: Collection<FunctionDescriptor>
@@ -102,11 +189,52 @@ class OverloadResolver(
private fun checkOverloadsInPackage(members: Collection<DeclarationDescriptorNonRoot>) {
if (members.size == 1) return
for (redeclarationGroup in overloadChecker.getPossibleRedeclarationGroups(members)) {
reportRedeclarations(findRedeclarations(redeclarationGroup))
val redeclarationsMap = LinkedHashMap<DeclarationDescriptorNonRoot, MutableSet<DeclarationDescriptorNonRoot>>()
for (redeclarationGroup in getPossibleRedeclarationGroups(members)) {
val redeclarations = findRedeclarations(redeclarationGroup)
redeclarations.forEach {
redeclarationsMap.getOrPut(it) { LinkedHashSet() }.addAll(redeclarations)
}
}
val reported = HashSet<DeclarationDescriptorNonRoot>()
for ((member, conflicting) in redeclarationsMap) {
if (!reported.contains(member)) {
reported.addAll(conflicting)
reportRedeclarations(conflicting)
}
}
}
private fun getPossibleRedeclarationGroups(members: Collection<DeclarationDescriptorNonRoot>): Collection<Collection<DeclarationDescriptorNonRoot>> {
val result = arrayListOf<Collection<DeclarationDescriptorNonRoot>>()
val nonPrivates = members.filter { !it.isPrivate() }
val bySourceFile = members.groupBy { DescriptorUtils.getContainingSourceFile(it) }
var hasGroupIncludingNonPrivateMembers = false
for ((sourceFile, membersInFile) in bySourceFile) {
// File member groups are interesting in redeclaration check if at least one file member is private.
if (membersInFile.any { it.isPrivate() }) {
hasGroupIncludingNonPrivateMembers = true
val group = LinkedHashSet<DeclarationDescriptorNonRoot>(nonPrivates) + membersInFile
result.add(group)
}
}
if (!hasGroupIncludingNonPrivateMembers && nonPrivates.size > 1) {
result.add(nonPrivates)
}
return result
}
private fun DeclarationDescriptor.isPrivate() =
this is DeclarationDescriptorWithVisibility &&
Visibilities.isPrivate(this.visibility)
private fun checkOverloadsInClass(members: Collection<CallableMemberDescriptor>) {
if (members.size == 1) return
reportRedeclarations(findRedeclarations(members))
@@ -115,8 +243,8 @@ class OverloadResolver(
private fun DeclarationDescriptor.isSynthesized() =
this is CallableMemberDescriptor && kind == CallableMemberDescriptor.Kind.SYNTHESIZED
private fun findRedeclarations(members: Collection<DeclarationDescriptorNonRoot>): Set<Pair<KtDeclaration?, DeclarationDescriptorNonRoot>> {
val redeclarations = linkedSetOf<Pair<KtDeclaration?, DeclarationDescriptorNonRoot>>()
private fun findRedeclarations(members: Collection<DeclarationDescriptorNonRoot>): Collection<DeclarationDescriptorNonRoot> {
val redeclarations = linkedSetOf<DeclarationDescriptorNonRoot>()
for (member1 in members) {
if (member1.isSynthesized()) continue
@@ -126,8 +254,7 @@ class OverloadResolver(
if (isTopLevelMainInDifferentFiles(member1, member2)) continue
if (!overloadChecker.isOverloadable(member1, member2)) {
val ktDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(member1) as KtDeclaration?
redeclarations.add(ktDeclaration to member1)
redeclarations.add(member1)
}
}
}
@@ -154,33 +281,16 @@ class OverloadResolver(
return file1 == null || file2 == null || file1 !== file2
}
private fun reportRedeclarations(redeclarations: Set<Pair<KtDeclaration?, DeclarationDescriptorNonRoot>>) {
private fun reportRedeclarations(redeclarations: Collection<DeclarationDescriptorNonRoot>) {
if (redeclarations.isEmpty()) return
val redeclarationsIterator = redeclarations.iterator()
val firstRedeclarationDescriptor = redeclarationsIterator.next().second
val otherRedeclarationDescriptor = redeclarationsIterator.check { it.hasNext() }?.next()?.second
for ((ktDeclaration, memberDescriptor) in redeclarations) {
if (ktDeclaration == null) continue
for (memberDescriptor in redeclarations) {
when (memberDescriptor) {
is PropertyDescriptor,
is ClassifierDescriptor -> {
trace.report(Errors.REDECLARATION.on(ktDeclaration, memberDescriptor.name.asString()))
}
is FunctionDescriptor -> {
val redeclarationDescriptor =
if (otherRedeclarationDescriptor == null)
firstRedeclarationDescriptor
else if (memberDescriptor == firstRedeclarationDescriptor)
otherRedeclarationDescriptor
else
firstRedeclarationDescriptor
trace.report(Errors.CONFLICTING_OVERLOADS.on(ktDeclaration, memberDescriptor,
redeclarationDescriptor.containingDeclaration))
}
is ClassifierDescriptor ->
reportOnDeclaration(trace, memberDescriptor) { Errors.REDECLARATION.on(it, redeclarations) }
is FunctionDescriptor ->
reportOnDeclaration(trace, memberDescriptor) { Errors.CONFLICTING_OVERLOADS.on(it, redeclarations) }
}
}
}
@@ -23,14 +23,13 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERR
import org.jetbrains.kotlin.descriptors.impl.ClassConstructorDescriptorImpl
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.reportOnDeclarationAs
import org.jetbrains.kotlin.diagnostics.reportOnDeclarationOrFail
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.incremental.record
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider
@@ -107,13 +106,13 @@ open class LazyClassMemberScope(
}
override fun overrideConflict(fromSuper: CallableMemberDescriptor, fromCurrent: CallableMemberDescriptor) {
val declaration = DescriptorToSourceUtils.descriptorToDeclaration(fromCurrent) as? KtDeclaration ?: error("fromCurrent can not be a fake override")
trace.report(Errors.CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromSuper.containingDeclaration))
reportOnDeclarationOrFail(trace, fromCurrent) { Errors.CONFLICTING_OVERLOADS.on(it, listOf(fromCurrent, fromSuper)) }
}
override fun inheritanceConflict(first: CallableMemberDescriptor, second: CallableMemberDescriptor) {
val thisClassDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(thisDescriptor) as? KtClassOrObject ?: error("No class declaration")
trace.report(Errors.CONFLICTING_INHERITED_MEMBERS.on(thisClassDeclaration, thisDescriptor, listOf(first, second)))
reportOnDeclarationAs<KtClassOrObject>(trace, thisDescriptor) { ktClassOrObject ->
Errors.CONFLICTING_INHERITED_MEMBERS.on(ktClassOrObject, thisDescriptor, listOf(first, second))
}
}
})
OverrideResolver.resolveUnknownVisibilities(result, trace)
@@ -16,8 +16,12 @@
package org.jetbrains.kotlin.resolve.scopes
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.reportOnDeclarationOrFail
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
@@ -77,32 +81,12 @@ class ThrowingLocalRedeclarationChecker(overloadChecker: OverloadChecker) : Abst
class TraceBasedLocalRedeclarationChecker(val trace: BindingTrace, overloadChecker: OverloadChecker): AbstractLocalRedeclarationChecker(overloadChecker) {
override fun handleRedeclaration(first: DeclarationDescriptor, second: DeclarationDescriptor) {
reportRedeclaration(first)
reportRedeclaration(second)
reportOnDeclarationOrFail(trace, first) { Errors.REDECLARATION.on(it, listOf(first, second))}
reportOnDeclarationOrFail(trace, second) { Errors.REDECLARATION.on(it, listOf(first, second))}
}
override fun handleConflictingOverloads(first: CallableMemberDescriptor, second: CallableMemberDescriptor) {
reportConflictingOverloads(first, second.containingDeclaration)
reportConflictingOverloads(second, first.containingDeclaration)
}
private fun reportConflictingOverloads(conflicting: CallableMemberDescriptor, withContainedIn: DeclarationDescriptor) {
val reportElement = DescriptorToSourceUtils.descriptorToDeclaration(conflicting)
if (reportElement != null) {
trace.report(Errors.CONFLICTING_OVERLOADS.on(reportElement, conflicting, withContainedIn))
}
else {
throw IllegalStateException("No declaration found for " + conflicting)
}
}
private fun reportRedeclaration(descriptor: DeclarationDescriptor) {
val firstElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)
if (firstElement != null) {
trace.report(Errors.REDECLARATION.on(firstElement, descriptor.name.asString()))
}
else {
throw IllegalStateException("No declaration found for " + descriptor)
}
reportOnDeclarationOrFail(trace, first) { Errors.CONFLICTING_OVERLOADS.on(it, listOf(first, second)) }
reportOnDeclarationOrFail(trace, second) { Errors.CONFLICTING_OVERLOADS.on(it, listOf(first, second)) }
}
}