Fixing interdependency between delegation and fake overrides

Main changes sit in OverrideResolver::generateOverridesAndDelegationInAClass()

Now fake overrides AND delegation are generated for supertypes before any processing is done for subclasses.
This commit is contained in:
Andrey Breslav
2012-08-15 16:15:04 +04:00
parent 734a9a02ef
commit 00305ba920
10 changed files with 62 additions and 100 deletions
@@ -42,7 +42,6 @@ import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.ScriptHeaderResolver;
import org.jetbrains.jet.lang.resolve.DelegationResolver;
import org.jetbrains.jet.lang.resolve.OverloadResolver;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver;
@@ -80,7 +79,6 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
private OverloadingConflictResolver overloadingConflictResolver;
private ImportsResolver importsResolver;
private ScriptHeaderResolver scriptHeaderResolver;
private DelegationResolver delegationResolver;
private OverloadResolver overloadResolver;
private OverrideResolver overrideResolver;
private TypeHierarchyResolver typeHierarchyResolver;
@@ -120,7 +118,6 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
this.overloadingConflictResolver = new OverloadingConflictResolver();
this.importsResolver = new ImportsResolver();
this.scriptHeaderResolver = new ScriptHeaderResolver();
this.delegationResolver = new DelegationResolver();
this.overloadResolver = new OverloadResolver();
this.overrideResolver = new OverrideResolver();
this.typeHierarchyResolver = new TypeHierarchyResolver();
@@ -132,7 +129,6 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
this.topDownAnalyzer.setBodyResolver(bodyResolver);
this.topDownAnalyzer.setContext(topDownAnalysisContext);
this.topDownAnalyzer.setDeclarationResolver(declarationResolver);
this.topDownAnalyzer.setDelegationResolver(delegationResolver);
this.topDownAnalyzer.setModuleDescriptor(moduleDescriptor);
this.topDownAnalyzer.setNamespaceFactory(namespaceFactory);
this.topDownAnalyzer.setOverloadResolver(overloadResolver);
@@ -214,9 +210,6 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly
scriptHeaderResolver.setTopDownAnalysisParameters(topDownAnalysisParameters);
scriptHeaderResolver.setTrace(bindingTrace);
delegationResolver.setContext(topDownAnalysisContext);
delegationResolver.setTrace(bindingTrace);
overloadResolver.setContext(topDownAnalysisContext);
overloadResolver.setTrace(bindingTrace);
@@ -39,7 +39,6 @@ import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.ScriptHeaderResolver;
import org.jetbrains.jet.lang.resolve.DelegationResolver;
import org.jetbrains.jet.lang.resolve.OverloadResolver;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver;
@@ -72,7 +71,6 @@ public class InjectorForTopDownAnalyzerBasic {
private OverloadingConflictResolver overloadingConflictResolver;
private ImportsResolver importsResolver;
private ScriptHeaderResolver scriptHeaderResolver;
private DelegationResolver delegationResolver;
private OverloadResolver overloadResolver;
private OverrideResolver overrideResolver;
private TypeHierarchyResolver typeHierarchyResolver;
@@ -107,7 +105,6 @@ public class InjectorForTopDownAnalyzerBasic {
this.overloadingConflictResolver = new OverloadingConflictResolver();
this.importsResolver = new ImportsResolver();
this.scriptHeaderResolver = new ScriptHeaderResolver();
this.delegationResolver = new DelegationResolver();
this.overloadResolver = new OverloadResolver();
this.overrideResolver = new OverrideResolver();
this.typeHierarchyResolver = new TypeHierarchyResolver();
@@ -116,7 +113,6 @@ public class InjectorForTopDownAnalyzerBasic {
this.topDownAnalyzer.setBodyResolver(bodyResolver);
this.topDownAnalyzer.setContext(topDownAnalysisContext);
this.topDownAnalyzer.setDeclarationResolver(declarationResolver);
this.topDownAnalyzer.setDelegationResolver(delegationResolver);
this.topDownAnalyzer.setModuleDescriptor(moduleDescriptor);
this.topDownAnalyzer.setNamespaceFactory(namespaceFactory);
this.topDownAnalyzer.setOverloadResolver(overloadResolver);
@@ -185,9 +181,6 @@ public class InjectorForTopDownAnalyzerBasic {
scriptHeaderResolver.setTopDownAnalysisParameters(topDownAnalysisParameters);
scriptHeaderResolver.setTrace(bindingTrace);
delegationResolver.setContext(topDownAnalysisContext);
delegationResolver.setTrace(bindingTrace);
overloadResolver.setContext(topDownAnalysisContext);
overloadResolver.setTrace(bindingTrace);
@@ -122,6 +122,7 @@ public class DeclarationsChecker {
private void checkOpenMembers(MutableClassDescriptor classDescriptor) {
for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) {
if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) continue;
JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), memberDescriptor);
if (member != null && classDescriptor.getModality() == Modality.FINAL && member.hasModifier(JetTokens.OPEN_KEYWORD)) {
trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member));
@@ -21,49 +21,21 @@ import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.psi.JetClassOrObject;
import org.jetbrains.jet.lang.psi.JetDelegationSpecifier;
import org.jetbrains.jet.lang.psi.JetDelegatorByExpressionSpecifier;
import org.jetbrains.jet.lang.types.JetType;
import javax.inject.Inject;
import java.util.Collection;
import java.util.Map;
/**
* @author abreslav
*/
public class DelegationResolver {
@NotNull
private TopDownAnalysisContext context;
@NotNull
private BindingTrace trace;
private DelegationResolver() {}
@Inject
public void setContext(@NotNull TopDownAnalysisContext context) {
this.context = context;
}
@Inject
public void setTrace(@NotNull BindingTrace trace) {
this.trace = trace;
}
public void process() {
addDelegatedMembers();
}
private void addDelegatedMembers() {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
addDelegatedMembers(entry.getKey(), entry.getValue());
}
for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
addDelegatedMembers(entry.getKey(), entry.getValue());
}
}
private void addDelegatedMembers(JetClassOrObject jetClass, MutableClassDescriptor classDescriptor) {
public static void addDelegatedMembers(@NotNull BindingTrace trace, @NotNull JetClassOrObject jetClass, @NotNull MutableClassDescriptor classDescriptor) {
for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
if (delegationSpecifier instanceof JetDelegatorByExpressionSpecifier) {
JetDelegatorByExpressionSpecifier specifier = (JetDelegatorByExpressionSpecifier) delegationSpecifier;
@@ -72,7 +72,7 @@ public class OverrideResolver {
public void process() {
//all created fake descriptors are stored to resolve visibility on them later
generateOverrides();
generateOverridesAndDelegation();
checkVisibility();
checkOverrides();
@@ -82,7 +82,7 @@ public class OverrideResolver {
/**
* Generate fake overrides and add overridden descriptors to existing descriptors.
*/
private void generateOverrides() {
private void generateOverridesAndDelegation() {
Set<MutableClassDescriptor> ourClasses = new HashSet<MutableClassDescriptor>();
ourClasses.addAll(context.getClasses().values());
ourClasses.addAll(context.getObjects().values());
@@ -90,33 +90,34 @@ public class OverrideResolver {
Set<ClassifierDescriptor> processed = new HashSet<ClassifierDescriptor>();
for (MutableClassDescriptor clazz : ourClasses) {
generateOverridesInAClass(clazz, processed, ourClasses);
generateOverridesAndDelegationInAClass(clazz, processed, ourClasses);
}
}
private void generateOverridesInAClass(@NotNull final MutableClassDescriptor classDescriptor,
private void generateOverridesAndDelegationInAClass(
@NotNull final MutableClassDescriptor classDescriptor,
@NotNull Set<ClassifierDescriptor> processed,
@NotNull Set<MutableClassDescriptor> ourClasses) {
@NotNull Set<MutableClassDescriptor> classesBeingAnalyzed
// to filter out classes such as stdlib and others that come from dependencies
) {
if (!processed.add(classDescriptor)) {
return;
}
// avoid processing stdlib classes twice
if (!ourClasses.contains(classDescriptor)) {
return;
}
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
ClassDescriptor superclass = (ClassDescriptor) supertype.getConstructor().getDeclarationDescriptor();
if (superclass instanceof MutableClassDescriptor) {
generateOverridesInAClass((MutableClassDescriptor) superclass, processed, ourClasses);
if (superclass instanceof MutableClassDescriptor && classesBeingAnalyzed.contains(superclass)) {
generateOverridesAndDelegationInAClass((MutableClassDescriptor) superclass, processed, classesBeingAnalyzed);
}
}
doGenerateOverridesInAClass(classDescriptor);
PsiElement declaration = BindingContextUtils.classDescriptorToDeclaration(trace.getBindingContext(), classDescriptor);
DelegationResolver.addDelegatedMembers(trace, (JetClassOrObject) declaration, classDescriptor);
generateOverridesInAClass(classDescriptor);
}
private void doGenerateOverridesInAClass(final MutableClassDescriptor classDescriptor) {
private void generateOverridesInAClass(final MutableClassDescriptor classDescriptor) {
List<CallableMemberDescriptor> membersFromSupertypes = getCallableMembersFromSupertypes(classDescriptor);
MultiMap<Name, CallableMemberDescriptor> membersFromSupertypesByName = groupDescriptorsByName(membersFromSupertypes);
@@ -160,7 +161,7 @@ public class OverrideResolver {
}
for (CallableMemberDescriptor memberDescriptor : classDescriptor.getAllCallableMembers()) {
JetDeclaration declaration = null;
if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
if (memberDescriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
PsiElement element = BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), memberDescriptor);
if (element instanceof JetDeclaration) {
declaration = (JetDeclaration) element;
@@ -453,21 +454,20 @@ public class OverrideResolver {
}
private void checkOverrideForMember(@NotNull CallableMemberDescriptor declared) {
if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
return;
}
JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
if (member == null) {
if (declared.getKind() != CallableMemberDescriptor.Kind.DELEGATION) {
throw new IllegalStateException(
"decriptor is not resolved to declaration" +
" and it is not delegate: " + declared + ", DELEGATED: " +
(declared.getKind() == CallableMemberDescriptor.Kind.DELEGATION));
"descriptor is not resolved to declaration" +
" and it is not delegate: " + declared);
}
return;
}
if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
return;
}
JetModifierList modifierList = member.getModifierList();
ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
boolean hasOverrideModifier = overrideNode != null;
@@ -549,8 +549,8 @@ public class OverrideResolver {
}
private void checkOverridesForParameters(CallableMemberDescriptor declared) {
boolean fakeOverride = declared.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
if (!fakeOverride) {
boolean noDeclaration = declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION;
if (!noDeclaration) {
// No check if the function is not marked as 'override'
JetModifierListOwner declaration =
(JetModifierListOwner) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
@@ -566,13 +566,13 @@ public class OverrideResolver {
// b) p1 must have the same name as p2
for (ValueParameterDescriptor parameterFromSubclass : declared.getValueParameters()) {
JetParameter parameter =
fakeOverride ? null :
noDeclaration ? null :
(JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), parameterFromSubclass);
JetClassOrObject classElement = fakeOverride ? (JetClassOrObject) BindingContextUtils
JetClassOrObject classElement = noDeclaration ? (JetClassOrObject) BindingContextUtils
.descriptorToDeclaration(trace.getBindingContext(), declared.getContainingDeclaration()) : null;
if (parameterFromSubclass.declaresDefaultValue() && !fakeOverride) {
if (parameterFromSubclass.declaresDefaultValue() && !noDeclaration) {
trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
}
@@ -583,7 +583,7 @@ public class OverrideResolver {
superWithDefault = true;
}
else {
if (fakeOverride) {
if (noDeclaration) {
trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, parameterFromSubclass));
}
else {
@@ -594,7 +594,7 @@ public class OverrideResolver {
}
if (!parameterFromSuperclass.getName().equals(parameterFromSubclass.getName())) {
if (fakeOverride) {
if (noDeclaration) {
trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(classElement, declared.getOverriddenDescriptors(), parameterFromSuperclass.getIndex() + 1));
}
else {
@@ -47,8 +47,6 @@ public class TopDownAnalyzer {
@NotNull
private TypeHierarchyResolver typeHierarchyResolver;
@NotNull
private DelegationResolver delegationResolver;
@NotNull
private OverrideResolver overrideResolver;
@NotNull
private OverloadResolver overloadResolver;
@@ -75,11 +73,6 @@ public class TopDownAnalyzer {
this.typeHierarchyResolver = typeHierarchyResolver;
}
@Inject
public void setDelegationResolver(@NotNull DelegationResolver delegationResolver) {
this.delegationResolver = delegationResolver;
}
@Inject
public void setOverrideResolver(@NotNull OverrideResolver overrideResolver) {
this.overrideResolver = overrideResolver;
@@ -131,7 +124,6 @@ public class TopDownAnalyzer {
typeHierarchyResolver.process(outerScope, owner, declarations);
declarationResolver.process(outerScope);
delegationResolver.process();
overrideResolver.process();
lockScopes();
@@ -0,0 +1,11 @@
class D(b: B) : C(b)
trait A {
fun foo() {}
}
trait B : A {}
class C(b : B) : B by b {
}
@@ -52,9 +52,15 @@ public abstract class AbstractJetDiagnosticsTest extends JetLiteFixture {
catch (IOException e) {
throw ExceptionUtils.rethrow(e);
}
return new JetCoreEnvironment(getTestRootDisposable(), CompileCompilerDependenciesTest.compilerConfigurationForTests(
ConfigurationKind.JDK_AND_ANNOTATIONS, TestJdkKind.MOCK_JDK, JetTestUtils.getAnnotationsJar(),
javaFilesDir));
return new JetCoreEnvironment(
getTestRootDisposable(),
CompileCompilerDependenciesTest.compilerConfigurationForTests(
ConfigurationKind.JDK_AND_ANNOTATIONS,
TestJdkKind.MOCK_JDK,
JetTestUtils.getAnnotationsJar(),
javaFilesDir
)
);
}
private static boolean writeJavaFile(@NotNull String fileName, @NotNull String content, @NotNull File javaFilesDir) {
@@ -15,15 +15,12 @@
*/
package org.jetbrains.jet.checkers;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
import java.io.File;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.test.TestMetadata;
import org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve;
import java.io.File;
/** This class is generated by {@link org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve}. DO NOT MODIFY MANUALLY */
public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve {
@@ -180,8 +177,12 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
@TestMetadata("DelegationNotTotrait.kt")
public void testDelegationNotTotrait() throws Exception {
// todo FIXME: enable this test
//doTest("compiler/testData/diagnostics/tests/DelegationNotTotrait.kt");
doTest("compiler/testData/diagnostics/tests/DelegationNotTotrait.kt");
}
@TestMetadata("Delegation_ScopeInitializationOrder.kt")
public void testDelegation_ScopeInitializationOrder() throws Exception {
doTest("compiler/testData/diagnostics/tests/Delegation_ScopeInitializationOrder.kt");
}
@TestMetadata("DiamondFunction.kt")
@@ -39,7 +39,6 @@ import org.jetbrains.jet.lang.resolve.QualifiedExpressionResolver;
import org.jetbrains.jet.lang.resolve.calls.OverloadingConflictResolver;
import org.jetbrains.jet.lang.resolve.ImportsResolver;
import org.jetbrains.jet.lang.resolve.ScriptHeaderResolver;
import org.jetbrains.jet.lang.resolve.DelegationResolver;
import org.jetbrains.jet.lang.resolve.OverloadResolver;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver;
@@ -72,7 +71,6 @@ public class InjectorForTopDownAnalyzerForJs {
private OverloadingConflictResolver overloadingConflictResolver;
private ImportsResolver importsResolver;
private ScriptHeaderResolver scriptHeaderResolver;
private DelegationResolver delegationResolver;
private OverloadResolver overloadResolver;
private OverrideResolver overrideResolver;
private TypeHierarchyResolver typeHierarchyResolver;
@@ -107,7 +105,6 @@ public class InjectorForTopDownAnalyzerForJs {
this.overloadingConflictResolver = new OverloadingConflictResolver();
this.importsResolver = new ImportsResolver();
this.scriptHeaderResolver = new ScriptHeaderResolver();
this.delegationResolver = new DelegationResolver();
this.overloadResolver = new OverloadResolver();
this.overrideResolver = new OverrideResolver();
this.typeHierarchyResolver = new TypeHierarchyResolver();
@@ -116,7 +113,6 @@ public class InjectorForTopDownAnalyzerForJs {
this.topDownAnalyzer.setBodyResolver(bodyResolver);
this.topDownAnalyzer.setContext(topDownAnalysisContext);
this.topDownAnalyzer.setDeclarationResolver(declarationResolver);
this.topDownAnalyzer.setDelegationResolver(delegationResolver);
this.topDownAnalyzer.setModuleDescriptor(moduleDescriptor);
this.topDownAnalyzer.setNamespaceFactory(namespaceFactory);
this.topDownAnalyzer.setOverloadResolver(overloadResolver);
@@ -185,9 +181,6 @@ public class InjectorForTopDownAnalyzerForJs {
scriptHeaderResolver.setTopDownAnalysisParameters(topDownAnalysisParameters);
scriptHeaderResolver.setTrace(bindingTrace);
delegationResolver.setContext(topDownAnalysisContext);
delegationResolver.setTrace(bindingTrace);
overloadResolver.setContext(topDownAnalysisContext);
overloadResolver.setTrace(bindingTrace);