001 /*
002 * Copyright 2010-2014 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.jet.backend.common;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
022 import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
023 import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
024 import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
025 import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
026 import org.jetbrains.jet.lang.resolve.name.Name;
027 import org.jetbrains.jet.lang.types.JetType;
028 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
029
030 import java.util.Arrays;
031 import java.util.Collection;
032 import java.util.List;
033
034 /**
035 * Backend-independent utility class.
036 */
037 public class CodegenUtil {
038
039 private CodegenUtil() {
040 }
041
042 // TODO: consider putting predefined method signatures here too.
043 public static final String EQUALS_METHOD_NAME = "equals";
044 public static final String TO_STRING_METHOD_NAME = "toString";
045 public static final String HASH_CODE_METHOD_NAME = "hashCode";
046
047 @Nullable
048 public static FunctionDescriptor getDeclaredFunctionByRawSignature(
049 @NotNull ClassDescriptor owner,
050 @NotNull Name name,
051 @NotNull ClassifierDescriptor returnedClassifier,
052 @NotNull ClassifierDescriptor... valueParameterClassifiers
053 ) {
054 Collection<FunctionDescriptor> functions = owner.getDefaultType().getMemberScope().getFunctions(name);
055 for (FunctionDescriptor function : functions) {
056 if (!CallResolverUtil.isOrOverridesSynthesized(function)
057 && function.getTypeParameters().isEmpty()
058 && valueParameterClassesMatch(function.getValueParameters(), Arrays.asList(valueParameterClassifiers))
059 && rawTypeMatches(function.getReturnType(), returnedClassifier)) {
060 return function;
061 }
062 }
063 return null;
064 }
065
066 public static FunctionDescriptor getAnyEqualsMethod() {
067 ClassDescriptor anyClass = KotlinBuiltIns.getInstance().getAny();
068 FunctionDescriptor function =
069 getDeclaredFunctionByRawSignature(anyClass, Name.identifier(EQUALS_METHOD_NAME),
070 KotlinBuiltIns.getInstance().getBoolean(),
071 anyClass);
072 assert function != null;
073 return function;
074 }
075
076 public static FunctionDescriptor getAnyToStringMethod() {
077 ClassDescriptor anyClass = KotlinBuiltIns.getInstance().getAny();
078 FunctionDescriptor function =
079 getDeclaredFunctionByRawSignature(anyClass, Name.identifier(TO_STRING_METHOD_NAME),
080 KotlinBuiltIns.getInstance().getString());
081 assert function != null;
082 return function;
083 }
084
085 public static FunctionDescriptor getAnyHashCodeMethod() {
086 ClassDescriptor anyClass = KotlinBuiltIns.getInstance().getAny();
087 FunctionDescriptor function =
088 getDeclaredFunctionByRawSignature(anyClass, Name.identifier(HASH_CODE_METHOD_NAME),
089 KotlinBuiltIns.getInstance().getInt());
090 assert function != null;
091 return function;
092 }
093
094 private static boolean valueParameterClassesMatch(
095 @NotNull List<ValueParameterDescriptor> parameters,
096 @NotNull List<ClassifierDescriptor> classifiers
097 ) {
098 if (parameters.size() != classifiers.size()) return false;
099 for (int i = 0; i < parameters.size(); i++) {
100 ValueParameterDescriptor parameterDescriptor = parameters.get(i);
101 ClassifierDescriptor classDescriptor = classifiers.get(i);
102 if (!rawTypeMatches(parameterDescriptor.getType(), classDescriptor)) {
103 return false;
104 }
105 }
106 return true;
107 }
108
109 private static boolean rawTypeMatches(JetType type, ClassifierDescriptor classifier) {
110 return type.getConstructor().getDeclarationDescriptor().getOriginal() == classifier.getOriginal();
111 }
112 }