Better diagnostics for conflicting overloads.
Skip declarations without sources in reporting, not when determining redeclaration groups: this allows emitting informative diagnostics for incremental compilation. Provide containing declaration with "kind", e.g., "package '<root>'", "class A", and so on.
This commit is contained in:
@@ -296,7 +296,7 @@ public interface Errors {
|
||||
|
||||
// Members
|
||||
|
||||
DiagnosticFactory2<KtDeclaration, CallableMemberDescriptor, CallableMemberDescriptor> CONFLICTING_OVERLOADS =
|
||||
DiagnosticFactory2<KtDeclaration, CallableMemberDescriptor, DeclarationDescriptor> CONFLICTING_OVERLOADS =
|
||||
DiagnosticFactory2.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
DiagnosticFactory0<KtNamedDeclaration> NON_FINAL_MEMBER_IN_FINAL_CLASS = DiagnosticFactory0.create(WARNING, modifierSetPosition(
|
||||
|
||||
+2
-1
@@ -611,7 +611,8 @@ 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: {1}", COMPACT_WITH_MODIFIERS, COMPACT_WITH_MODIFIERS);
|
||||
MAP.put(CONFLICTING_OVERLOADS, "''{0}'' conflicts with another declaration in {1}", COMPACT_WITH_MODIFIERS,
|
||||
DECLARATION_NAME_WITH_KIND);
|
||||
|
||||
MAP.put(FUNCTION_EXPECTED, "Expression ''{0}''{1} cannot be invoked as a function. " +
|
||||
"The function '" + OperatorNameConventions.INVOKE.asString() + "()' is not found",
|
||||
|
||||
@@ -76,6 +76,19 @@ object Renderers {
|
||||
|
||||
@JvmField val NAME: Renderer<Named> = Renderer { it.name.asString() }
|
||||
|
||||
@JvmField val DECLARATION_NAME_WITH_KIND: Renderer<DeclarationDescriptor> = Renderer {
|
||||
val declarationKindWithSpace = when (it) {
|
||||
is PackageFragmentDescriptor -> "package "
|
||||
is ClassDescriptor -> "${it.renderKind()} "
|
||||
is ConstructorDescriptor -> "constructor "
|
||||
is PropertyGetterDescriptor -> "property getter "
|
||||
is PropertySetterDescriptor -> "property setter "
|
||||
is FunctionDescriptor -> "function "
|
||||
else -> throw AssertionError("Unexpected declaration kind: $it")
|
||||
}
|
||||
"$declarationKindWithSpace'${it.name.asString()}'"
|
||||
}
|
||||
|
||||
@JvmField val NAME_OF_PARENT_OR_FILE: Renderer<DeclarationDescriptor> = Renderer {
|
||||
if (DescriptorUtils.isTopLevelDeclaration(it) && it is DeclarationDescriptorWithVisibility && it.visibility == Visibilities.PRIVATE) {
|
||||
"file"
|
||||
|
||||
@@ -52,7 +52,7 @@ public class OverloadResolver {
|
||||
MultiMap<ClassDescriptor, ConstructorDescriptor> inClasses = findConstructorsInNestedClasses(c);
|
||||
|
||||
for (Map.Entry<KtClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
|
||||
checkOverloadsInAClass(entry.getValue(), entry.getKey(), inClasses.get(entry.getValue()));
|
||||
checkOverloadsInAClass(entry.getValue(), inClasses.get(entry.getValue()));
|
||||
}
|
||||
checkOverloadsInPackages(c);
|
||||
}
|
||||
@@ -88,27 +88,12 @@ public class OverloadResolver {
|
||||
OverloadUtil.groupModulePackageMembersByFqName(c, overloadFilter);
|
||||
|
||||
for (Map.Entry<FqNameUnsafe, Collection<CallableMemberDescriptor>> e : membersByName.entrySet()) {
|
||||
FqNameUnsafe fqName = e.getKey().parent();
|
||||
checkOverloadsInPackage(e.getValue(), fqName);
|
||||
checkOverloadsInPackage(e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private static String nameForErrorMessage(ClassDescriptor classDescriptor, KtClassOrObject jetClass) {
|
||||
String name = jetClass.getName();
|
||||
if (name != null) {
|
||||
return name;
|
||||
}
|
||||
if (jetClass instanceof KtObjectDeclaration) {
|
||||
// must be companion object
|
||||
name = classDescriptor.getContainingDeclaration().getName().asString();
|
||||
return "companion object " + name;
|
||||
}
|
||||
// safe
|
||||
return "<unknown>";
|
||||
}
|
||||
|
||||
private void checkOverloadsInAClass(
|
||||
ClassDescriptorWithResolutionScopes classDescriptor, KtClassOrObject klass,
|
||||
ClassDescriptorWithResolutionScopes classDescriptor,
|
||||
Collection<ConstructorDescriptor> nestedClassConstructors
|
||||
) {
|
||||
MultiMap<Name, CallableMemberDescriptor> functionsByName = MultiMap.create();
|
||||
@@ -122,31 +107,24 @@ public class OverloadResolver {
|
||||
}
|
||||
|
||||
for (Map.Entry<Name, Collection<CallableMemberDescriptor>> e : functionsByName.entrySet()) {
|
||||
checkOverloadsInClass(e.getValue(), classDescriptor, klass);
|
||||
checkOverloadsInClass(e.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void checkOverloadsInPackage(
|
||||
@NotNull Collection<CallableMemberDescriptor> members,
|
||||
@NotNull FqNameUnsafe packageFQN
|
||||
) {
|
||||
private void checkOverloadsInPackage(@NotNull Collection<CallableMemberDescriptor> members) {
|
||||
if (members.size() == 1) return;
|
||||
|
||||
for (Collection<? extends CallableMemberDescriptor> redeclarationGroup : OverloadUtil.getPossibleRedeclarationGroups(members)) {
|
||||
Set<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarations = findRedeclarations(redeclarationGroup);
|
||||
// TODO: don't render FQ name here, extract this logic to somewhere
|
||||
reportRedeclarations(packageFQN.isRoot() ? "root package" : packageFQN.asString(), redeclarations);
|
||||
reportRedeclarations(redeclarations);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkOverloadsInClass(
|
||||
@NotNull Collection<CallableMemberDescriptor> members,
|
||||
@NotNull ClassDescriptor classDescriptor,
|
||||
@NotNull KtClassOrObject ktClass
|
||||
) {
|
||||
private void checkOverloadsInClass(@NotNull Collection<CallableMemberDescriptor> members) {
|
||||
if (members.size() == 1) return;
|
||||
|
||||
reportRedeclarations(nameForErrorMessage(classDescriptor, ktClass), findRedeclarations(members));
|
||||
reportRedeclarations(findRedeclarations(members));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -164,9 +142,7 @@ public class OverloadResolver {
|
||||
}
|
||||
|
||||
KtDeclaration ktDeclaration = (KtDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(member);
|
||||
if (ktDeclaration != null) {
|
||||
redeclarations.add(Pair.create(ktDeclaration, member));
|
||||
}
|
||||
redeclarations.add(Pair.create(ktDeclaration, member));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -196,10 +172,7 @@ public class OverloadResolver {
|
||||
return file == null || file2 == null || file != file2;
|
||||
}
|
||||
|
||||
private void reportRedeclarations(
|
||||
@NotNull String functionContainer,
|
||||
@NotNull Set<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarations
|
||||
) {
|
||||
private void reportRedeclarations(@NotNull Set<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarations) {
|
||||
if (redeclarations.isEmpty()) return;
|
||||
|
||||
Iterator<Pair<KtDeclaration, CallableMemberDescriptor>> redeclarationsIterator = redeclarations.iterator();
|
||||
@@ -210,6 +183,8 @@ public class OverloadResolver {
|
||||
|
||||
for (Pair<KtDeclaration, CallableMemberDescriptor> redeclaration : redeclarations) {
|
||||
KtDeclaration ktDeclaration = redeclaration.getFirst();
|
||||
if (ktDeclaration == null) continue;
|
||||
|
||||
CallableMemberDescriptor memberDescriptor = redeclaration.getSecond();
|
||||
|
||||
CallableMemberDescriptor redeclarationDescriptor;
|
||||
@@ -227,7 +202,8 @@ public class OverloadResolver {
|
||||
trace.report(Errors.REDECLARATION.on(ktDeclaration, memberDescriptor.getName().asString()));
|
||||
}
|
||||
else {
|
||||
trace.report(Errors.CONFLICTING_OVERLOADS.on(ktDeclaration, memberDescriptor, redeclarationDescriptor));
|
||||
trace.report(Errors.CONFLICTING_OVERLOADS.on(ktDeclaration, memberDescriptor,
|
||||
redeclarationDescriptor.getContainingDeclaration()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -108,7 +108,7 @@ open class LazyClassMemberScope(
|
||||
|
||||
override fun conflict(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))
|
||||
trace.report(Errors.CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromSuper.containingDeclaration))
|
||||
}
|
||||
})
|
||||
OverrideResolver.resolveUnknownVisibilities(result, trace)
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
compiler/testData/cli/jvm/conflictingOverloads.kt:1:1: error: 'public fun a(): kotlin.collections.List<kotlin.Int>' conflicts with another declaration: public fun a(): kotlin.collections.List<kotlin.String>
|
||||
compiler/testData/cli/jvm/conflictingOverloads.kt:1:1: error: 'public fun a(): kotlin.collections.List<kotlin.Int>' conflicts with another declaration in package '<root>'
|
||||
fun a(): List<Int> = null!!
|
||||
^
|
||||
compiler/testData/cli/jvm/conflictingOverloads.kt:2:1: error: 'public fun a(): kotlin.collections.List<kotlin.String>' conflicts with another declaration: public fun a(): kotlin.collections.List<kotlin.Int>
|
||||
compiler/testData/cli/jvm/conflictingOverloads.kt:2:1: error: 'public fun a(): kotlin.collections.List<kotlin.String>' conflicts with another declaration in package '<root>'
|
||||
fun a(): List<String> = null!!
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.diagnostics.TypeMismatchDueToTypeProjectionsData;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticRenderer;
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers;
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs;
|
||||
import org.jetbrains.kotlin.js.resolve.diagnostics.JsCallDataHtmlRenderer;
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||
@@ -137,8 +138,8 @@ public class IdeErrorMessages {
|
||||
|
||||
MAP.put(MANY_IMPL_MEMBER_NOT_IMPLEMENTED, "<html>{0} must override {1}<br />because it inherits many implementations of it</html>",
|
||||
RENDER_CLASS_OR_OBJECT, DescriptorRenderer.HTML);
|
||||
MAP.put(CONFLICTING_OVERLOADS, "<html>''{0}''<br />conflicts with another declaration: {1}</html>",
|
||||
IdeRenderers.HTML_COMPACT_WITH_MODIFIERS, IdeRenderers.HTML_COMPACT_WITH_MODIFIERS);
|
||||
MAP.put(CONFLICTING_OVERLOADS, "<html>''{0}''<br />conflicts with another declaration in {1}</html>",
|
||||
IdeRenderers.HTML_COMPACT_WITH_MODIFIERS, Renderers.DECLARATION_NAME_WITH_KIND);
|
||||
|
||||
MAP.put(RESULT_TYPE_MISMATCH, "<html>Function return type mismatch." +
|
||||
"<table><tr><td>Expected:</td><td>{1}</td></tr>" +
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ERROR: 'public open fun foo(): kotlin.Unit' conflicts with another declaration: public open fun foo(): kotlin.Unit
|
||||
// ERROR: 'public open fun foo(): kotlin.Unit' conflicts with another declaration: public open fun foo(): kotlin.Unit
|
||||
// ERROR: 'public open fun foo(): kotlin.Unit' conflicts with another declaration in class 'C'
|
||||
// ERROR: 'public open fun foo(): kotlin.Unit' conflicts with another declaration in class 'C'
|
||||
interface I {
|
||||
open fun foo(){}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<!-- conflictingOverloadsClass1 -->
|
||||
<html>
|
||||
'<b>public</b> <b>final</b> <b>fun</b> lol(x: kotlin.Int): kotlin.Int'<br />conflicts with another declaration: <b>public</b> <b>final</b> <b>fun</b> lol(y: kotlin.Int): kotlin.Int</html>
|
||||
'<b>public</b> <b>final</b> <b>fun</b> lol(x: kotlin.Int): kotlin.Int'<br />conflicts with another declaration in class 'conflictingOverloads'</html>
|
||||
@@ -1,3 +1,3 @@
|
||||
<!-- conflictingOverloadsClass2 -->
|
||||
<html>
|
||||
'<b>public</b> <b>final</b> <b>fun</b> lol(y: kotlin.Int): kotlin.Int'<br />conflicts with another declaration: <b>public</b> <b>final</b> <b>fun</b> lol(x: kotlin.Int): kotlin.Int</html>
|
||||
'<b>public</b> <b>final</b> <b>fun</b> lol(y: kotlin.Int): kotlin.Int'<br />conflicts with another declaration in class 'conflictingOverloads'</html>
|
||||
@@ -1,2 +1,2 @@
|
||||
<!-- conflictingOverloadsDefaultPackage1 -->
|
||||
'public fun foo(x: kotlin.Int): kotlin.Int' conflicts with another declaration: public fun foo(y: kotlin.Int): kotlin.Int
|
||||
'public fun foo(x: kotlin.Int): kotlin.Int' conflicts with another declaration in package '<root>'
|
||||
@@ -1,2 +1,2 @@
|
||||
<!-- conflictingOverloadsDefaultPackage2 -->
|
||||
'public fun foo(y: kotlin.Int): kotlin.Int' conflicts with another declaration: public fun foo(x: kotlin.Int): kotlin.Int
|
||||
'public fun foo(y: kotlin.Int): kotlin.Int' conflicts with another declaration in package '<root>'
|
||||
@@ -1,2 +1,2 @@
|
||||
<!-- constructorsRedeclaration1 -->
|
||||
'public constructor Element(x: kotlin.String)' conflicts with another declaration: public constructor Element(x: kotlin.String)
|
||||
'public constructor Element(x: kotlin.String)' conflicts with another declaration in class 'Element'
|
||||
@@ -1,2 +1,2 @@
|
||||
<!-- constructorsRedeclaration2 -->
|
||||
'public constructor Element(x: kotlin.String)' conflicts with another declaration: public constructor Element(x: kotlin.String)
|
||||
'public constructor Element(x: kotlin.String)' conflicts with another declaration in class 'Element'
|
||||
@@ -1,2 +1,2 @@
|
||||
<!-- constructorsRedeclarationTopLevel1 -->
|
||||
'public fun Element(x: kotlin.String): kotlin.Unit' conflicts with another declaration: public constructor Element(x: kotlin.String)
|
||||
'public fun Element(x: kotlin.String): kotlin.Unit' conflicts with another declaration in class 'Element'
|
||||
@@ -1,2 +1,2 @@
|
||||
<!-- constructorsRedeclarationTopLevel2 -->
|
||||
'public constructor Element(x: kotlin.String)' conflicts with another declaration: public fun Element(x: kotlin.String): kotlin.Unit
|
||||
'public constructor Element(x: kotlin.String)' conflicts with another declaration in package '<root>'
|
||||
+1
-1
@@ -5,7 +5,7 @@ Compiling files:
|
||||
src/A.kt
|
||||
End of files
|
||||
COMPILATION FAILED
|
||||
'public constructor A(x: kotlin.String)' conflicts with another declaration: public constructor A(x: kotlin.String)
|
||||
'public constructor A(x: kotlin.String)' conflicts with another declaration in package '<root>'
|
||||
|
||||
|
||||
Cleaning output files:
|
||||
|
||||
@@ -6,4 +6,4 @@ Compiling files:
|
||||
src/fun2.kt
|
||||
End of files
|
||||
COMPILATION FAILED
|
||||
'public fun function(): kotlin.Unit' conflicts with another declaration: public fun function(): kotlin.Unit
|
||||
'public fun function(): kotlin.Unit' conflicts with another declaration in package 'test'
|
||||
+1
-1
@@ -6,4 +6,4 @@ Compiling files:
|
||||
src/fun2.kt
|
||||
End of files
|
||||
COMPILATION FAILED
|
||||
'public constructor function()' conflicts with another declaration: public constructor function()
|
||||
'public constructor function()' conflicts with another declaration in package 'test'
|
||||
Reference in New Issue
Block a user