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.Collection;
034 import java.util.HashSet;
035 import java.util.List;
036 import java.util.Set;
037
038 public final class DescriptorResolverUtils {
039 private DescriptorResolverUtils() {
040 }
041
042 @NotNull
043 public static <D extends CallableMemberDescriptor> Collection<D> resolveOverrides(
044 @NotNull Name name,
045 @NotNull Collection<D> membersFromSupertypes,
046 @NotNull Collection<D> membersFromCurrent,
047 @NotNull ClassDescriptor classDescriptor,
048 @NotNull final ErrorReporter errorReporter
049 ) {
050 final Set<D> result = new HashSet<D>();
051
052 OverridingUtil.generateOverridesInFunctionGroup(
053 name, membersFromSupertypes, membersFromCurrent, classDescriptor,
054 new OverridingUtil.DescriptorSink() {
055 @Override
056 @SuppressWarnings("unchecked")
057 public void addFakeOverride(@NotNull CallableMemberDescriptor fakeOverride) {
058 OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, new Function1<CallableMemberDescriptor, Unit>() {
059 @Override
060 public Unit invoke(@NotNull CallableMemberDescriptor descriptor) {
061 errorReporter.reportCannotInferVisibility(descriptor);
062 return Unit.INSTANCE$;
063 }
064 });
065 result.add((D) fakeOverride);
066 }
067
068 @Override
069 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
070 // nop
071 }
072 }
073 );
074
075 return result;
076 }
077
078 @Nullable
079 public static ValueParameterDescriptor getAnnotationParameterByName(@NotNull Name name, @NotNull ClassDescriptor annotationClass) {
080 Collection<ConstructorDescriptor> constructors = annotationClass.getConstructors();
081 assert constructors.size() == 1 : "Annotation class descriptor must have only one constructor";
082
083 for (ValueParameterDescriptor parameter : constructors.iterator().next().getValueParameters()) {
084 if (parameter.getName().equals(name)) {
085 return parameter;
086 }
087 }
088
089 return null;
090 }
091
092 public static boolean isObjectMethodInInterface(@NotNull JavaMember member) {
093 return member.getContainingClass().isInterface() && member instanceof JavaMethod && isObjectMethod((JavaMethod) member);
094 }
095
096 public static boolean isObjectMethod(@NotNull JavaMethod method) {
097 String name = method.getName().asString();
098 if (name.equals("toString") || name.equals("hashCode")) {
099 return method.getValueParameters().isEmpty();
100 }
101 else if (name.equals("equals")) {
102 return isMethodWithOneParameterWithFqName(method, "java.lang.Object");
103 }
104 return false;
105 }
106
107 private static boolean isMethodWithOneParameterWithFqName(@NotNull JavaMethod method, @NotNull String fqName) {
108 List<JavaValueParameter> parameters = method.getValueParameters();
109 if (parameters.size() == 1) {
110 JavaType type = parameters.get(0).getType();
111 if (type instanceof JavaClassifierType) {
112 JavaClassifier classifier = ((JavaClassifierType) type).getClassifier();
113 if (classifier instanceof JavaClass) {
114 FqName classFqName = ((JavaClass) classifier).getFqName();
115 return classFqName != null && classFqName.asString().equals(fqName);
116 }
117 }
118 }
119 return false;
120 }
121 }