From 635f8ea62693ee9c1dd42345e67ad16a0a0b3ec9 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 6 Jun 2014 14:45:21 +0400 Subject: [PATCH] BuilderfactoryForDuplicateSignatureDiagnostics moved out of GenerationState --- ...ctoryForDuplicateSignatureDiagnostics.java | 185 ++++++++++++++++++ .../jet/codegen/state/GenerationState.java | 159 +-------------- 2 files changed, 192 insertions(+), 152 deletions(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/state/BuilderfactoryForDuplicateSignatureDiagnostics.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/BuilderfactoryForDuplicateSignatureDiagnostics.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/BuilderfactoryForDuplicateSignatureDiagnostics.java new file mode 100644 index 00000000000..1d8fa16b5d0 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/BuilderfactoryForDuplicateSignatureDiagnostics.java @@ -0,0 +1,185 @@ +/* + * Copyright 2010-2014 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.jet.codegen.state; + +import com.intellij.psi.PsiElement; +import com.intellij.util.containers.MultiMap; +import kotlin.Function1; +import kotlin.KotlinPackage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.ClassBuilderFactory; +import org.jetbrains.jet.codegen.SignatureCollectingClassBuilderFactory; +import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; +import org.jetbrains.jet.lang.resolve.java.diagnostics.*; +import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; + +import java.util.*; + +import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.DELEGATION; +import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE; + +class BuilderfactoryForDuplicateSignatureDiagnostics extends SignatureCollectingClassBuilderFactory { + + private final JetTypeMapper typeMapper; + private final BindingContext bindingContext; + private final DiagnosticHolder diagnostics; + + public BuilderfactoryForDuplicateSignatureDiagnostics( + @NotNull ClassBuilderFactory builderFactory, + @NotNull JetTypeMapper typeMapper, + @NotNull BindingContext bindingContext, + @NotNull DiagnosticHolder diagnostics + ) { + super(builderFactory); + this.typeMapper = typeMapper; + this.bindingContext = bindingContext; + this.diagnostics = diagnostics; + } + + @Override + protected void handleClashingSignatures( + @NotNull ConflictingJvmDeclarationsData data + ) { + Collection elements = new LinkedHashSet(); + + boolean allDelegatedToTraitImpls = KotlinPackage.all( + data.getSignatureOrigins(), + new Function1() { + @Override + public Boolean invoke(JvmDeclarationOrigin origin) { + return origin.getOriginKind() == JvmDeclarationOriginKind.DELEGATION_TO_TRAIT_IMPL; + } + } + ); + for (JvmDeclarationOrigin origin : data.getSignatureOrigins()) { + PsiElement element = origin.getElement(); + if (element == null || allDelegatedToTraitImpls) { + element = data.getClassOrigin().getElement(); + } + if (element != null) { + elements.add(element); + } + } + + for (PsiElement element : elements) { + diagnostics.report(ErrorsJvm.CONFLICTING_JVM_DECLARATIONS.on(element, data)); + } + } + + @Override + protected void onClassDone( + @NotNull JvmDeclarationOrigin classOrigin, + @Nullable String classInternalName, + boolean hasDuplicateSignatures + ) { + DeclarationDescriptor descriptor = classOrigin.getDescriptor(); + if (!(descriptor instanceof ClassDescriptor)) return; + + ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; + + MultiMap groupedBySignature = MultiMap.create(); + Queue queue = + new LinkedList(classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()); + while (!queue.isEmpty()) { + DeclarationDescriptor member = queue.poll(); + if (member instanceof DeclarationDescriptorWithVisibility && + ((DeclarationDescriptorWithVisibility) member).getVisibility() == Visibilities.INVISIBLE_FAKE) { + // a member of super is not visible: no override + continue; + } + if (member instanceof CallableMemberDescriptor && + CallResolverUtil.isOrOverridesSynthesized((CallableMemberDescriptor) member)) { + // if a signature clashes with a SAM-adapter or something like that, there's no harm + continue; + } + if (member instanceof PropertyDescriptor) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) member; + + PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); + if (getter != null) { + queue.add(getter); + } + PropertySetterDescriptor setter = propertyDescriptor.getSetter(); + if (setter != null) { + queue.add(setter); + } + } + else if (member instanceof FunctionDescriptor) { + FunctionDescriptor functionDescriptor = (FunctionDescriptor) member; + + JvmMethodSignature methodSignature = typeMapper.mapSignature(functionDescriptor); + RawSignature rawSignature = new RawSignature( + methodSignature.getAsmMethod().getName(), + methodSignature.getAsmMethod().getDescriptor(), + MemberKind.METHOD + ); + groupedBySignature.putValue(rawSignature, functionDescriptor); + } + } + + signatures: + for (Map.Entry> entry : groupedBySignature.entrySet()) { + RawSignature rawSignature = entry.getKey(); + Collection members = entry.getValue(); + + if (members.size() <= 1) continue; + + PsiElement memberElement = null; + int nonFakeCount = 0; + for (CallableMemberDescriptor member : members) { + // + if (member.getKind() != FAKE_OVERRIDE) { + nonFakeCount++; + // If there's more than one real element, the clashing signature is already reported. + // Only clashes between fake overrides are interesting here + if (nonFakeCount > 1) continue signatures; + + if (member.getKind() != DELEGATION) { + // Delegates don't have declarations in the code + memberElement = BindingContextUtils.callableDescriptorToDeclaration(bindingContext, member); + if (memberElement == null && member instanceof PropertyAccessorDescriptor) { + memberElement = BindingContextUtils.callableDescriptorToDeclaration( + bindingContext, + ((PropertyAccessorDescriptor) member).getCorrespondingProperty() + ); + } + } + } + } + + PsiElement elementToReportOn = memberElement == null ? classOrigin.getElement() : memberElement; + if (elementToReportOn == null) return; + + List origins = KotlinPackage.map( + members, + new Function1() { + @Override + public JvmDeclarationOrigin invoke(CallableMemberDescriptor descriptor) { + return DiagnosticsPackage.OtherOrigin(descriptor); + } + }); + ConflictingJvmDeclarationsData data = + new ConflictingJvmDeclarationsData(classInternalName, classOrigin, rawSignature, origins); + diagnostics.report(ErrorsJvm.ACCIDENTAL_OVERRIDE.on(elementToReportOn, data)); + } + } +} diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java index 0970f2d5dd3..27637df19e8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/GenerationState.java @@ -17,34 +17,26 @@ package org.jetbrains.jet.codegen.state; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.util.containers.MultiMap; -import kotlin.Function1; -import kotlin.KotlinPackage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.codegen.*; import org.jetbrains.jet.codegen.binding.CodegenBinding; import org.jetbrains.jet.codegen.inline.InlineCodegenUtil; import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods; -import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; +import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; import org.jetbrains.jet.lang.diagnostics.DiagnosticHolder; import org.jetbrains.jet.lang.psi.JetClassOrObject; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.reflect.ReflectionTypes; import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace; -import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; -import org.jetbrains.jet.lang.resolve.java.diagnostics.*; -import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; import org.jetbrains.jet.lang.resolve.name.FqName; -import java.util.*; - -import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.DELEGATION; -import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE; +import java.util.Collection; +import java.util.Collections; +import java.util.List; public class GenerationState { public interface GenerateClassFilter { @@ -153,7 +145,8 @@ public class GenerationState { this.typeMapper = new JetTypeMapper(this.bindingContext, classBuilderMode); this.intrinsics = new IntrinsicMethods(); - this.classFileFactory = new ClassFileFactory(this, new BuilderfactoryForDuplicateSignatureDiagnostics(builderFactory, diagnostics)); + this.classFileFactory = new ClassFileFactory(this, new BuilderfactoryForDuplicateSignatureDiagnostics( + builderFactory, typeMapper, bindingContext, diagnostics)); this.generateNotNullAssertions = generateNotNullAssertions; this.generateNotNullParamAssertions = generateNotNullParamAssertions; @@ -274,142 +267,4 @@ public class GenerationState { public String getModuleId() { return moduleId; } - - private class BuilderfactoryForDuplicateSignatureDiagnostics extends SignatureCollectingClassBuilderFactory { - - private final DiagnosticHolder diagnostics; - - public BuilderfactoryForDuplicateSignatureDiagnostics(@NotNull ClassBuilderFactory builderFactory, DiagnosticHolder diagnostics) { - super(builderFactory); - this.diagnostics = diagnostics; - } - - @Override - protected void handleClashingSignatures( - @NotNull ConflictingJvmDeclarationsData data - ) { - Collection elements = new LinkedHashSet(); - - boolean allDelegatedToTraitImpls = KotlinPackage.all( - data.getSignatureOrigins(), - new Function1() { - @Override - public Boolean invoke(JvmDeclarationOrigin origin) { - return origin.getOriginKind() == JvmDeclarationOriginKind.DELEGATION_TO_TRAIT_IMPL; - } - } - ); - for (JvmDeclarationOrigin origin : data.getSignatureOrigins()) { - PsiElement element = origin.getElement(); - if (element == null || allDelegatedToTraitImpls) { - element = data.getClassOrigin().getElement(); - } - if (element != null) { - elements.add(element); - } - } - - for (PsiElement element : elements) { - diagnostics.report(ErrorsJvm.CONFLICTING_JVM_DECLARATIONS.on(element, data)); - } - } - - @Override - protected void onClassDone( - @NotNull JvmDeclarationOrigin classOrigin, - @Nullable String classInternalName, - boolean hasDuplicateSignatures - ) { - DeclarationDescriptor descriptor = classOrigin.getDescriptor(); - if (!(descriptor instanceof ClassDescriptor)) return; - - ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; - - MultiMap groupedBySignature = MultiMap.create(); - Queue queue = - new LinkedList(classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()); - while (!queue.isEmpty()) { - DeclarationDescriptor member = queue.poll(); - if (member instanceof DeclarationDescriptorWithVisibility && - ((DeclarationDescriptorWithVisibility) member).getVisibility() == Visibilities.INVISIBLE_FAKE) { - // a member of super is not visible: no override - continue; - } - if (member instanceof CallableMemberDescriptor && - CallResolverUtil.isOrOverridesSynthesized((CallableMemberDescriptor) member)) { - // if a signature clashes with a SAM-adapter or something like that, there's no harm - continue; - } - if (member instanceof PropertyDescriptor) { - PropertyDescriptor propertyDescriptor = (PropertyDescriptor) member; - - PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); - if (getter != null) { - queue.add(getter); - } - PropertySetterDescriptor setter = propertyDescriptor.getSetter(); - if (setter != null) { - queue.add(setter); - } - } - else if (member instanceof FunctionDescriptor) { - FunctionDescriptor functionDescriptor = (FunctionDescriptor) member; - - JvmMethodSignature methodSignature = typeMapper.mapSignature(functionDescriptor); - RawSignature rawSignature = new RawSignature( - methodSignature.getAsmMethod().getName(), - methodSignature.getAsmMethod().getDescriptor(), - MemberKind.METHOD - ); - groupedBySignature.putValue(rawSignature, functionDescriptor); - } - } - - signatures: - for (Map.Entry> entry : groupedBySignature.entrySet()) { - RawSignature rawSignature = entry.getKey(); - Collection members = entry.getValue(); - - if (members.size() <= 1) continue; - - PsiElement memberElement = null; - int nonFakeCount = 0; - for (CallableMemberDescriptor member : members) { - // - if (member.getKind() != FAKE_OVERRIDE) { - nonFakeCount++; - // If there's more than one real element, the clashing signature is already reported. - // Only clashes between fake overrides are interesting here - if (nonFakeCount > 1) continue signatures; - - if (member.getKind() != DELEGATION) { - // Delegates don't have declarations in the code - memberElement = BindingContextUtils.callableDescriptorToDeclaration(getBindingContext(), member); - if (memberElement == null && member instanceof PropertyAccessorDescriptor) { - memberElement = BindingContextUtils.callableDescriptorToDeclaration( - getBindingContext(), - ((PropertyAccessorDescriptor) member).getCorrespondingProperty() - ); - } - } - } - } - - PsiElement elementToReportOn = memberElement == null ? classOrigin.getElement() : memberElement; - if (elementToReportOn == null) return; - - List origins = KotlinPackage.map( - members, - new Function1() { - @Override - public JvmDeclarationOrigin invoke(CallableMemberDescriptor descriptor) { - return DiagnosticsPackage.OtherOrigin(descriptor); - } - }); - ConflictingJvmDeclarationsData data = - new ConflictingJvmDeclarationsData(classInternalName, classOrigin, rawSignature, origins); - diagnostics.report(ErrorsJvm.ACCIDENTAL_OVERRIDE.on(elementToReportOn, data)); - } - } - } }