diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java index d25f2b4936e..e286a56da51 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverrideResolver.java @@ -29,7 +29,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; -import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptorLite; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; @@ -77,13 +76,13 @@ public class OverrideResolver { Set ourClasses = new HashSet(c.getAllClasses()); Set processed = new HashSet(); - for (MutableClassDescriptorLite klass : ContainerUtil.reverse(c.getClassesTopologicalOrder())) { - if (klass instanceof MutableClassDescriptor && ourClasses.contains(klass)) { - generateOverridesAndDelegationInAClass((MutableClassDescriptor) klass, processed, ourClasses); + for (MutableClassDescriptor klass : ContainerUtil.reverse(c.getClassesTopologicalOrder())) { + if (ourClasses.contains(klass)) { + generateOverridesAndDelegationInAClass(klass, processed, ourClasses); - MutableClassDescriptorLite classObject = klass.getClassObjectDescriptor(); - if (classObject instanceof MutableClassDescriptor) { - generateOverridesAndDelegationInAClass((MutableClassDescriptor) classObject, processed, ourClasses); + MutableClassDescriptor classObject = klass.getClassObjectDescriptor(); + if (classObject != null) { + generateOverridesAndDelegationInAClass(classObject, processed, ourClasses); } } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java index 6a2c4c1197f..a3fce7cd8cb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TopDownAnalysisContext.java @@ -25,7 +25,7 @@ import kotlin.Function1; import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptorLite; +import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; @@ -44,7 +44,7 @@ public class TopDownAnalysisContext implements BodiesResolveContext { private final Map classes = Maps.newLinkedHashMap(); protected final Map packageFragments = Maps.newHashMap(); protected final Set files = new LinkedHashSet(); - private List classesTopologicalOrder = null; + private List classesTopologicalOrder = null; private final Map declaringScopes = Maps.newHashMap(); private final Map functions = Maps.newLinkedHashMap(); @@ -183,11 +183,11 @@ public class TopDownAnalysisContext implements BodiesResolveContext { } @NotNull - public List getClassesTopologicalOrder() { + public List getClassesTopologicalOrder() { return classesTopologicalOrder; } - public void setClassesTopologicalOrder(@NotNull List classesTopologicalOrder) { + public void setClassesTopologicalOrder(@NotNull List classesTopologicalOrder) { this.classesTopologicalOrder = classesTopologicalOrder; } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java index 3d5869c2f5c..6428b7360b0 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/TypeHierarchyResolver.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve; import com.google.common.collect.Lists; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNameIdentifierOwner; +import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -218,38 +219,38 @@ public class TypeHierarchyResolver { } } - private static List topologicallySortClassesAndObjects(@NotNull TopDownAnalysisContext c) { + @NotNull + private static List topologicallySortClassesAndObjects(@NotNull TopDownAnalysisContext c) { // A topsort is needed only for better diagnostics: // edges that get removed to disconnect loops are more reasonable in this case //noinspection unchecked - return DFS.topologicalOrder( + List orderedClasses = DFS.topologicalOrder( (Iterable) c.getAllClasses(), - new DFS.Neighbors() { + new DFS.Neighbors() { @NotNull @Override - public Iterable getNeighbors(MutableClassDescriptorLite current) { - List result = Lists.newArrayList(); - for (JetType supertype : current.getSupertypes()) { - DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor(); - if (declarationDescriptor instanceof MutableClassDescriptorLite) { - MutableClassDescriptorLite classDescriptor = (MutableClassDescriptorLite) declarationDescriptor; - result.add(classDescriptor); + public Iterable getNeighbors(ClassDescriptor current) { + List result = Lists.newArrayList(); + for (JetType supertype : current.getDefaultType().getConstructor().getSupertypes()) { + DeclarationDescriptor descriptor = supertype.getConstructor().getDeclarationDescriptor(); + if (descriptor instanceof ClassDescriptor) { + result.add((ClassDescriptor) descriptor); } } return result; } - }); - + } + ); + return KotlinPackage.filterIsInstance(orderedClasses, MutableClassDescriptor.class); } private void detectAndDisconnectLoops(@NotNull TopDownAnalysisContext c) { - // Loop detection and disconnection List tasks = new ArrayList(); - for (final MutableClassDescriptorLite klass : c.getClassesTopologicalOrder()) { + for (final MutableClassDescriptor klass : c.getClassesTopologicalOrder()) { for (final JetType supertype : klass.getSupertypes()) { ClassifierDescriptor supertypeDescriptor = supertype.getConstructor().getDeclarationDescriptor(); - if (supertypeDescriptor instanceof MutableClassDescriptorLite) { - MutableClassDescriptorLite superclass = (MutableClassDescriptorLite) supertypeDescriptor; + if (supertypeDescriptor instanceof ClassDescriptor) { + ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor; if (isReachable(superclass, klass, new HashSet())) { tasks.add(new Runnable() { @Override @@ -269,15 +270,19 @@ public class TypeHierarchyResolver { } // Temporary. Duplicates logic from LazyClassTypeConstructor.isReachable - private static boolean isReachable(MutableClassDescriptorLite from, MutableClassDescriptorLite to, Set visited) { + private static boolean isReachable( + @NotNull ClassDescriptor from, + @NotNull MutableClassDescriptor to, + @NotNull Set visited + ) { if (!visited.add(from)) return false; - for (JetType supertype : from.getSupertypes()) { + for (JetType supertype : from.getDefaultType().getConstructor().getSupertypes()) { TypeConstructor supertypeConstructor = supertype.getConstructor(); if (supertypeConstructor.getDeclarationDescriptor() == to) { return true; } ClassifierDescriptor superclass = supertypeConstructor.getDeclarationDescriptor(); - if (superclass instanceof MutableClassDescriptorLite && isReachable((MutableClassDescriptorLite) superclass, to, visited)) { + if (superclass instanceof ClassDescriptor && isReachable((ClassDescriptor) superclass, to, visited)) { return true; } } diff --git a/compiler/testData/diagnostics/tests/CyclicHierarchy.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.kt similarity index 100% rename from compiler/testData/diagnostics/tests/CyclicHierarchy.kt rename to compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.kt diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt new file mode 100644 index 00000000000..de8b50c27e4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt @@ -0,0 +1,17 @@ +// FILE: A.java + +interface A extends C { + void foo(); +} + +// FILE: B.kt + +trait B : A { + fun bar() +} + +// FILE: C.java + +interface C extends B { + void baz(); +} diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.kt new file mode 100644 index 00000000000..6d1e0dfeb12 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.kt @@ -0,0 +1,11 @@ +// FILE: J.java + +class J extends K { + void foo() {} +} + +// FILE: K.kt + +class K : J() { + fun bar() {} +} diff --git a/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.kt new file mode 100644 index 00000000000..1df66a7bd15 --- /dev/null +++ b/compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.kt @@ -0,0 +1,17 @@ +// FILE: I.kt + +open class I : K() { + fun foo() {} +} + +// FILE: J.java + +class J extends I { + void bar() {} +} + +// FILE: K.kt + +open class K : J() { + fun baz() {} +} diff --git a/compiler/testData/diagnostics/tests/regressions/kt303.kt b/compiler/testData/diagnostics/tests/cyclicHierarchy/kt303.kt similarity index 100% rename from compiler/testData/diagnostics/tests/regressions/kt303.kt rename to compiler/testData/diagnostics/tests/cyclicHierarchy/kt303.kt diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 9a3fa94a836..608fc8248bc 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -33,7 +33,7 @@ import org.jetbrains.jet.checkers.AbstractJetDiagnosticsTest; @InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class, JetDiagnosticsTestGenerated.TailRecursion.class}) public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { @TestMetadata("compiler/testData/diagnostics/tests") - @InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.CallableReference.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Evaluate.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.Imports.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inline.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NamedArguments.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.ThisAndSuper.class, Tests.Unit.class, Tests.Varargs.class, Tests.When.class}) + @InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.CallableReference.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ClassObjects.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.CyclicHierarchy.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.DelegatedProperty.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Evaluate.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.Imports.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inline.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NamedArguments.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Numbers.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.Suppress.class, Tests.ThisAndSuper.class, Tests.Unit.class, Tests.Varargs.class, Tests.When.class}) public static class Tests extends AbstractJetDiagnosticsTest { @TestMetadata("Abstract.kt") public void testAbstract() throws Exception { @@ -149,11 +149,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/CovariantOverrideType.kt"); } - @TestMetadata("CyclicHierarchy.kt") - public void testCyclicHierarchy() throws Exception { - doTest("compiler/testData/diagnostics/tests/CyclicHierarchy.kt"); - } - @TestMetadata("DefaultValuesTypechecking.kt") public void testDefaultValuesTypechecking() throws Exception { doTest("compiler/testData/diagnostics/tests/DefaultValuesTypechecking.kt"); @@ -1822,6 +1817,39 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { } + @TestMetadata("compiler/testData/diagnostics/tests/cyclicHierarchy") + public static class CyclicHierarchy extends AbstractJetDiagnosticsTest { + public void testAllFilesPresentInCyclicHierarchy() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/diagnostics/tests/cyclicHierarchy"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("cyclicHierarchy.kt") + public void testCyclicHierarchy() throws Exception { + doTest("compiler/testData/diagnostics/tests/cyclicHierarchy/cyclicHierarchy.kt"); + } + + @TestMetadata("javaKotlinJavaCycle.kt") + public void testJavaKotlinJavaCycle() throws Exception { + doTest("compiler/testData/diagnostics/tests/cyclicHierarchy/javaKotlinJavaCycle.kt"); + } + + @TestMetadata("kotlinJavaCycle.kt") + public void testKotlinJavaCycle() throws Exception { + doTest("compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaCycle.kt"); + } + + @TestMetadata("kotlinJavaKotlinCycle.kt") + public void testKotlinJavaKotlinCycle() throws Exception { + doTest("compiler/testData/diagnostics/tests/cyclicHierarchy/kotlinJavaKotlinCycle.kt"); + } + + @TestMetadata("kt303.kt") + public void testKt303() throws Exception { + doTest("compiler/testData/diagnostics/tests/cyclicHierarchy/kt303.kt"); + } + + } + @TestMetadata("compiler/testData/diagnostics/tests/dataClasses") public static class DataClasses extends AbstractJetDiagnosticsTest { public void testAllFilesPresentInDataClasses() throws Exception { @@ -5739,11 +5767,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest("compiler/testData/diagnostics/tests/regressions/kt302.kt"); } - @TestMetadata("kt303.kt") - public void testKt303() throws Exception { - doTest("compiler/testData/diagnostics/tests/regressions/kt303.kt"); - } - @TestMetadata("kt306.kt") public void testKt306() throws Exception { doTest("compiler/testData/diagnostics/tests/regressions/kt306.kt"); @@ -7104,6 +7127,7 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { suite.addTestSuite(ClassObjects.class); suite.addTest(ControlFlowAnalysis.innerSuite()); suite.addTestSuite(ControlStructures.class); + suite.addTestSuite(CyclicHierarchy.class); suite.addTestSuite(DataClasses.class); suite.addTest(DataFlow.innerSuite()); suite.addTestSuite(DataFlowInfoTraversal.class);