001 /*
002 * Copyright 2010-2015 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.kotlin.load.java.components;
018
019 import kotlin.Unit;
020 import kotlin.jvm.functions.Function1;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
024 import org.jetbrains.kotlin.descriptors.ClassDescriptor;
025 import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
026 import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
027 import org.jetbrains.kotlin.load.java.structure.*;
028 import org.jetbrains.kotlin.name.FqName;
029 import org.jetbrains.kotlin.name.Name;
030 import org.jetbrains.kotlin.resolve.OverridingUtil;
031 import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter;
032
033 import java.util.*;
034
035 public final class DescriptorResolverUtils {
036 private DescriptorResolverUtils() {
037 }
038
039 @NotNull
040 public static <D extends CallableMemberDescriptor> Collection<D> resolveOverrides(
041 @NotNull Name name,
042 @NotNull Collection<D> membersFromSupertypes,
043 @NotNull Collection<D> membersFromCurrent,
044 @NotNull ClassDescriptor classDescriptor,
045 @NotNull final ErrorReporter errorReporter
046 ) {
047 final Set<D> result = new LinkedHashSet<D>();
048
049 OverridingUtil.generateOverridesInFunctionGroup(
050 name, membersFromSupertypes, membersFromCurrent, classDescriptor,
051 new OverridingUtil.DescriptorSink() {
052 @Override
053 @SuppressWarnings("unchecked")
054 public void addFakeOverride(@NotNull CallableMemberDescriptor fakeOverride) {
055 OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, new Function1<CallableMemberDescriptor, Unit>() {
056 @Override
057 public Unit invoke(@NotNull CallableMemberDescriptor descriptor) {
058 errorReporter.reportCannotInferVisibility(descriptor);
059 return Unit.INSTANCE$;
060 }
061 });
062 result.add((D) fakeOverride);
063 }
064
065 @Override
066 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
067 // nop
068 }
069 }
070 );
071
072 return result;
073 }
074
075 @Nullable
076 public static ValueParameterDescriptor getAnnotationParameterByName(@NotNull Name name, @NotNull ClassDescriptor annotationClass) {
077 Collection<ConstructorDescriptor> constructors = annotationClass.getConstructors();
078 if (constructors.size() != 1) return null;
079
080 for (ValueParameterDescriptor parameter : constructors.iterator().next().getValueParameters()) {
081 if (parameter.getName().equals(name)) {
082 return parameter;
083 }
084 }
085
086 return null;
087 }
088
089 public static boolean isObjectMethodInInterface(@NotNull JavaMember member) {
090 return member.getContainingClass().isInterface() && member instanceof JavaMethod && isObjectMethod((JavaMethod) member);
091 }
092
093 public static boolean isObjectMethod(@NotNull JavaMethod method) {
094 String name = method.getName().asString();
095 if (name.equals("toString") || name.equals("hashCode")) {
096 return method.getValueParameters().isEmpty();
097 }
098 else if (name.equals("equals")) {
099 return isMethodWithOneParameterWithFqName(method, "java.lang.Object");
100 }
101 return false;
102 }
103
104 private static boolean isMethodWithOneParameterWithFqName(@NotNull JavaMethod method, @NotNull String fqName) {
105 List<JavaValueParameter> parameters = method.getValueParameters();
106 if (parameters.size() == 1) {
107 JavaType type = parameters.get(0).getType();
108 if (type instanceof JavaClassifierType) {
109 JavaClassifier classifier = ((JavaClassifierType) type).getClassifier();
110 if (classifier instanceof JavaClass) {
111 FqName classFqName = ((JavaClass) classifier).getFqName();
112 return classFqName != null && classFqName.asString().equals(fqName);
113 }
114 }
115 }
116 return false;
117 }
118 }