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 FakeOverrideVisibilityResolver fakeOverrideVisibilityResolver;
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 setFakeOverrideVisibilityResolver(FakeOverrideVisibilityResolver fakeOverrideVisibilityResolver) {
085 this.fakeOverrideVisibilityResolver = fakeOverrideVisibilityResolver;
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,
215 fakeOverrideVisibilityResolver));
216 }
217
218 if (isEnumClassObject(owner)) {
219 for (FunctionDescriptor functionDescriptor : functionsFromCurrent) {
220 if (!(isEnumValueOfMethod(functionDescriptor) || isEnumValuesMethod(functionDescriptor))) {
221 functions.add(functionDescriptor);
222 }
223 }
224 }
225 else {
226 functions.addAll(functionsFromCurrent);
227 }
228
229 return functions;
230 }
231
232 @Nullable
233 private static ClassDescriptorFromJvmBytecode findClassInScope(@NotNull JetScope memberScope, @NotNull Name name) {
234 ClassifierDescriptor classifier = memberScope.getClassifier(name);
235 if (classifier instanceof ClassDescriptorFromJvmBytecode) {
236 return (ClassDescriptorFromJvmBytecode) classifier;
237 }
238 return null;
239 }
240
241 // E.g. we have foo.Bar.Baz class declared in Java. It will produce the following descriptors structure:
242 // namespace foo
243 // +-- class Bar
244 // | +-- class Baz
245 // +-- namespace Bar
246 // We need to find class 'Baz' in namespace 'foo.Bar'.
247 @Nullable
248 private static ClassDescriptorFromJvmBytecode findClassInNamespace(@NotNull NamespaceDescriptor namespace, @NotNull Name name) {
249 // First, try to find in namespace directly
250 ClassDescriptorFromJvmBytecode found = findClassInScope(namespace.getMemberScope(), name);
251 if (found != null) {
252 return found;
253 }
254
255 // If unsuccessful, try to find class of the same name as current (class 'foo.Bar')
256 NamespaceDescriptorParent parent = namespace.getContainingDeclaration();
257 if (parent instanceof NamespaceDescriptor) {
258 // Calling recursively, looking for 'Bar' in 'foo'
259 ClassDescriptor classForCurrentNamespace = findClassInNamespace((NamespaceDescriptor) parent, namespace.getName());
260 if (classForCurrentNamespace == null) {
261 return null;
262 }
263
264 // Try to find nested class 'Baz' in class 'foo.Bar'
265 return findClassInScope(DescriptorUtils.getStaticNestedClassesScope(classForCurrentNamespace), name);
266 }
267 return null;
268 }
269
270 @Nullable
271 public static SamConstructorDescriptor resolveSamConstructor(@NotNull NamespaceDescriptor owner, @NotNull NamedMembers namedMembers) {
272 if (namedMembers.getSamInterface() != null) {
273 ClassDescriptorFromJvmBytecode klass = findClassInNamespace(owner, namedMembers.getName());
274 if (klass != null) {
275 return createSamConstructorFunction(owner, klass);
276 }
277 }
278 return null;
279 }
280
281 @Nullable
282 private static SimpleFunctionDescriptor resolveSamAdapter(@NotNull SimpleFunctionDescriptor original) {
283 return isSamAdapterNecessary(original) ? (SimpleFunctionDescriptor) createSamAdapterFunction(original) : null;
284 }
285
286 @NotNull
287 private JetType makeReturnType(
288 @NotNull JavaType returnType,
289 @NotNull JavaMethod method,
290 @NotNull TypeVariableResolver typeVariableResolver
291 ) {
292 TypeUsage typeUsage = annotationResolver.hasReadonlyAnnotation(method) && !annotationResolver.hasMutableAnnotation(method)
293 ? TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
294 : TypeUsage.MEMBER_SIGNATURE_COVARIANT;
295 JetType transformedType = typeTransformer.transformToType(returnType, typeUsage, typeVariableResolver);
296
297 if (annotationResolver.hasNotNullAnnotation(method)) {
298 return TypeUtils.makeNotNullable(transformedType);
299 }
300 else {
301 return transformedType;
302 }
303 }
304
305 @NotNull
306 private static Set<SimpleFunctionDescriptor> getFunctionsFromSupertypes(@NotNull Name name, @NotNull ClassDescriptor descriptor) {
307 Set<SimpleFunctionDescriptor> result = new LinkedHashSet<SimpleFunctionDescriptor>();
308 for (JetType supertype : descriptor.getTypeConstructor().getSupertypes()) {
309 for (FunctionDescriptor function : supertype.getMemberScope().getFunctions(name)) {
310 result.add((SimpleFunctionDescriptor) function);
311 }
312 }
313 return result;
314 }
315 }