001 /*
002 * Copyright 2010-2013 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.lang.resolve.java.resolver;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.descriptors.*;
022 import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
023 import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
024 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
025 import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
026 import org.jetbrains.jet.lang.resolve.java.descriptor.JavaMethodDescriptor;
027 import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor;
028 import org.jetbrains.jet.lang.resolve.java.scope.NamedMembers;
029 import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
030 import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
031 import org.jetbrains.jet.lang.resolve.name.Name;
032 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
033 import org.jetbrains.jet.lang.types.JetType;
034 import org.jetbrains.jet.lang.types.TypeUtils;
035
036 import javax.inject.Inject;
037 import java.util.*;
038
039 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
040 import static org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils.resolveOverrides;
041 import static org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils.*;
042
043 public final class JavaFunctionResolver {
044 private JavaTypeTransformer typeTransformer;
045 private JavaResolverCache cache;
046 private JavaTypeParameterResolver typeParameterResolver;
047 private JavaValueParameterResolver valueParameterResolver;
048 private JavaAnnotationResolver annotationResolver;
049 private ExternalSignatureResolver externalSignatureResolver;
050 private ErrorReporter errorReporter;
051 private MethodSignatureChecker signatureChecker;
052
053 @Inject
054 public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
055 this.typeTransformer = typeTransformer;
056 }
057
058 @Inject
059 public void setCache(JavaResolverCache cache) {
060 this.cache = cache;
061 }
062
063 @Inject
064 public void setTypeParameterResolver(JavaTypeParameterResolver typeParameterResolver) {
065 this.typeParameterResolver = typeParameterResolver;
066 }
067
068 @Inject
069 public void setValueParameterResolver(JavaValueParameterResolver valueParameterResolver) {
070 this.valueParameterResolver = valueParameterResolver;
071 }
072
073 @Inject
074 public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) {
075 this.annotationResolver = annotationResolver;
076 }
077
078 @Inject
079 public void setExternalSignatureResolver(ExternalSignatureResolver externalSignatureResolver) {
080 this.externalSignatureResolver = externalSignatureResolver;
081 }
082
083 @Inject
084 public void setErrorReporter(ErrorReporter errorReporter) {
085 this.errorReporter = errorReporter;
086 }
087
088 @Inject
089 public void setSignatureChecker(MethodSignatureChecker signatureChecker) {
090 this.signatureChecker = signatureChecker;
091 }
092
093 @Nullable
094 SimpleFunctionDescriptor resolveFunctionMutely(@NotNull JavaMethod method, @NotNull ClassOrNamespaceDescriptor owner) {
095 return resolveMethodToFunctionDescriptor(method, owner, false);
096 }
097
098 @Nullable
099 private SimpleFunctionDescriptor resolveMethodToFunctionDescriptor(
100 @NotNull JavaMethod method,
101 @NotNull ClassOrNamespaceDescriptor ownerDescriptor,
102 boolean record
103 ) {
104 if (!DescriptorResolverUtils.isCorrectOwnerForEnumMember(ownerDescriptor, method)) {
105 return null;
106 }
107
108 JavaType returnJavaType = method.getReturnType();
109 if (returnJavaType == null) {
110 // This means that the method is a constructor
111 return null;
112 }
113
114 SimpleFunctionDescriptor alreadyResolved = cache.getMethod(method);
115 if (alreadyResolved != null) {
116 return alreadyResolved;
117 }
118
119 SimpleFunctionDescriptorImpl functionDescriptorImpl = new JavaMethodDescriptor(
120 ownerDescriptor,
121 annotationResolver.resolveAnnotations(method),
122 method.getName()
123 );
124
125 JavaTypeParameterResolver.Initializer typeParameterInitializer = typeParameterResolver.resolveTypeParameters(functionDescriptorImpl, method);
126 typeParameterInitializer.initialize();
127 List<TypeParameterDescriptor> methodTypeParameters = typeParameterInitializer.getDescriptors();
128
129 TypeVariableResolver typeVariableResolver = new TypeVariableResolverImpl(methodTypeParameters, functionDescriptorImpl);
130
131 List<ValueParameterDescriptor> valueParameters =
132 valueParameterResolver.resolveValueParameters(functionDescriptorImpl, method, typeVariableResolver);
133 JetType returnType = makeReturnType(returnJavaType, method, typeVariableResolver);
134
135
136 List<String> signatureErrors;
137 List<FunctionDescriptor> superFunctions;
138 ExternalSignatureResolver.AlternativeMethodSignature effectiveSignature;
139
140 if (ownerDescriptor instanceof NamespaceDescriptor) {
141 superFunctions = Collections.emptyList();
142 effectiveSignature = externalSignatureResolver
143 .resolveAlternativeMethodSignature(method, false, returnType, null, valueParameters, methodTypeParameters);
144 signatureErrors = effectiveSignature.getErrors();
145 }
146 else if (ownerDescriptor instanceof ClassDescriptor) {
147 ExternalSignatureResolver.PropagatedMethodSignature propagated = externalSignatureResolver
148 .resolvePropagatedSignature(method, (ClassDescriptor) ownerDescriptor, returnType, null, valueParameters,
149 methodTypeParameters);
150
151 superFunctions = propagated.getSuperMethods();
152
153 effectiveSignature = externalSignatureResolver
154 .resolveAlternativeMethodSignature(method, !superFunctions.isEmpty(), propagated.getReturnType(),
155 propagated.getReceiverType(), propagated.getValueParameters(),
156 propagated.getTypeParameters());
157
158 signatureErrors = new ArrayList<String>(propagated.getErrors());
159 signatureErrors.addAll(effectiveSignature.getErrors());
160 }
161 else {
162 throw new IllegalStateException("Unknown class or namespace descriptor: " + ownerDescriptor);
163 }
164
165 functionDescriptorImpl.initialize(
166 effectiveSignature.getReceiverType(),
167 DescriptorUtils.getExpectedThisObjectIfNeeded(ownerDescriptor),
168 effectiveSignature.getTypeParameters(),
169 effectiveSignature.getValueParameters(),
170 effectiveSignature.getReturnType(),
171 Modality.convertFromFlags(method.isAbstract(), !method.isFinal()),
172 method.getVisibility(),
173 /*isInline = */ false
174 );
175
176 if (record) {
177 cache.recordMethod(method, functionDescriptorImpl);
178 }
179
180 signatureChecker.checkSignature(method, record, functionDescriptorImpl, signatureErrors, superFunctions);
181
182 return functionDescriptorImpl;
183 }
184
185 @NotNull
186 public Set<FunctionDescriptor> resolveFunctionGroupForClass(@NotNull NamedMembers members, @NotNull ClassOrNamespaceDescriptor owner) {
187 Name methodName = members.getName();
188
189 Set<SimpleFunctionDescriptor> functionsFromCurrent = new HashSet<SimpleFunctionDescriptor>();
190 for (JavaMethod method : members.getMethods()) {
191 SimpleFunctionDescriptor function = resolveMethodToFunctionDescriptor(method, owner, true);
192 if (function != null) {
193 functionsFromCurrent.add(function);
194 SimpleFunctionDescriptor samAdapter = resolveSamAdapter(function);
195 if (samAdapter != null) {
196 functionsFromCurrent.add(samAdapter);
197 }
198 }
199 }
200
201 if (owner instanceof NamespaceDescriptor) {
202 SamConstructorDescriptor samConstructor = resolveSamConstructor((NamespaceDescriptor) owner, members);
203 if (samConstructor != null) {
204 functionsFromCurrent.add(samConstructor);
205 }
206 }
207
208 Set<FunctionDescriptor> functions = new HashSet<FunctionDescriptor>();
209 if (owner instanceof ClassDescriptor) {
210 ClassDescriptor classDescriptor = (ClassDescriptor) owner;
211
212 Collection<SimpleFunctionDescriptor> functionsFromSupertypes = getFunctionsFromSupertypes(methodName, classDescriptor);
213
214 functions.addAll(resolveOverrides(methodName, functionsFromSupertypes, functionsFromCurrent, classDescriptor, errorReporter));
215 }
216
217 if (isEnumClassObject(owner)) {
218 for (FunctionDescriptor functionDescriptor : functionsFromCurrent) {
219 if (!(isEnumValueOfMethod(functionDescriptor) || isEnumValuesMethod(functionDescriptor))) {
220 functions.add(functionDescriptor);
221 }
222 }
223 }
224 else {
225 functions.addAll(functionsFromCurrent);
226 }
227
228 return functions;
229 }
230
231 @Nullable
232 private static ClassDescriptorFromJvmBytecode findClassInScope(@NotNull JetScope memberScope, @NotNull Name name) {
233 ClassifierDescriptor classifier = memberScope.getClassifier(name);
234 if (classifier instanceof ClassDescriptorFromJvmBytecode) {
235 return (ClassDescriptorFromJvmBytecode) classifier;
236 }
237 return null;
238 }
239
240 // E.g. we have foo.Bar.Baz class declared in Java. It will produce the following descriptors structure:
241 // namespace foo
242 // +-- class Bar
243 // | +-- class Baz
244 // +-- namespace Bar
245 // We need to find class 'Baz' in namespace 'foo.Bar'.
246 @Nullable
247 private static ClassDescriptorFromJvmBytecode findClassInNamespace(@NotNull NamespaceDescriptor namespace, @NotNull Name name) {
248 // First, try to find in namespace directly
249 ClassDescriptorFromJvmBytecode found = findClassInScope(namespace.getMemberScope(), name);
250 if (found != null) {
251 return found;
252 }
253
254 // If unsuccessful, try to find class of the same name as current (class 'foo.Bar')
255 NamespaceDescriptorParent parent = namespace.getContainingDeclaration();
256 if (parent instanceof NamespaceDescriptor) {
257 // Calling recursively, looking for 'Bar' in 'foo'
258 ClassDescriptor classForCurrentNamespace = findClassInNamespace((NamespaceDescriptor) parent, namespace.getName());
259 if (classForCurrentNamespace == null) {
260 return null;
261 }
262
263 // Try to find nested class 'Baz' in class 'foo.Bar'
264 return findClassInScope(DescriptorUtils.getStaticNestedClassesScope(classForCurrentNamespace), name);
265 }
266 return null;
267 }
268
269 @Nullable
270 public static SamConstructorDescriptor resolveSamConstructor(@NotNull NamespaceDescriptor owner, @NotNull NamedMembers namedMembers) {
271 if (namedMembers.getSamInterface() != null) {
272 ClassDescriptorFromJvmBytecode klass = findClassInNamespace(owner, namedMembers.getName());
273 if (klass != null) {
274 return createSamConstructorFunction(owner, klass);
275 }
276 }
277 return null;
278 }
279
280 @Nullable
281 private static SimpleFunctionDescriptor resolveSamAdapter(@NotNull SimpleFunctionDescriptor original) {
282 return isSamAdapterNecessary(original) ? (SimpleFunctionDescriptor) createSamAdapterFunction(original) : null;
283 }
284
285 @NotNull
286 private JetType makeReturnType(
287 @NotNull JavaType returnType,
288 @NotNull JavaMethod method,
289 @NotNull TypeVariableResolver typeVariableResolver
290 ) {
291 TypeUsage typeUsage = annotationResolver.hasReadonlyAnnotation(method) && !annotationResolver.hasMutableAnnotation(method)
292 ? TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
293 : TypeUsage.MEMBER_SIGNATURE_COVARIANT;
294 JetType transformedType = typeTransformer.transformToType(returnType, typeUsage, typeVariableResolver);
295
296 if (annotationResolver.hasNotNullAnnotation(method)) {
297 return TypeUtils.makeNotNullable(transformedType);
298 }
299 else {
300 return transformedType;
301 }
302 }
303
304 @NotNull
305 private static Set<SimpleFunctionDescriptor> getFunctionsFromSupertypes(@NotNull Name name, @NotNull ClassDescriptor descriptor) {
306 Set<SimpleFunctionDescriptor> result = new LinkedHashSet<SimpleFunctionDescriptor>();
307 for (JetType supertype : descriptor.getTypeConstructor().getSupertypes()) {
308 for (FunctionDescriptor function : supertype.getMemberScope().getFunctions(name)) {
309 result.add((SimpleFunctionDescriptor) function);
310 }
311 }
312 return result;
313 }
314 }