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 com.google.common.collect.Lists;
020 import com.google.common.collect.Sets;
021 import com.intellij.openapi.diagnostic.Logger;
022 import com.intellij.psi.PsiClass;
023 import com.intellij.psi.PsiMethod;
024 import com.intellij.psi.PsiType;
025 import com.intellij.psi.util.PsiFormatUtil;
026 import com.intellij.util.containers.ContainerUtil;
027 import org.jetbrains.annotations.NotNull;
028 import org.jetbrains.annotations.Nullable;
029 import org.jetbrains.jet.lang.descriptors.*;
030 import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorParent;
031 import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
032 import org.jetbrains.jet.lang.resolve.*;
033 import org.jetbrains.jet.lang.resolve.java.*;
034 import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
035 import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSignatureData;
036 import org.jetbrains.jet.lang.resolve.java.kotlinSignature.SignaturesPropagationData;
037 import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils;
038 import org.jetbrains.jet.lang.resolve.java.provider.*;
039 import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
040 import org.jetbrains.jet.lang.resolve.name.Name;
041 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
042 import org.jetbrains.jet.lang.types.*;
043 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
044
045 import javax.inject.Inject;
046 import java.util.Collections;
047 import java.util.HashSet;
048 import java.util.List;
049 import java.util.Set;
050
051 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
052 import static org.jetbrains.jet.lang.resolve.OverridingUtil.*;
053 import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.JAVA;
054 import static org.jetbrains.jet.lang.resolve.java.provider.DeclarationOrigin.KOTLIN;
055 import static org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils.*;
056
057 public final class JavaFunctionResolver {
058 private static final Logger LOG = Logger.getInstance(JavaFunctionResolver.class);
059
060 private JavaTypeTransformer typeTransformer;
061 private BindingTrace trace;
062 private JavaSignatureResolver signatureResolver;
063 private JavaValueParameterResolver parameterResolver;
064 private JavaAnnotationResolver annotationResolver;
065
066 public JavaFunctionResolver() {
067 }
068
069 @Inject
070 public void setTypeTransformer(JavaTypeTransformer typeTransformer) {
071 this.typeTransformer = typeTransformer;
072 }
073
074 @Inject
075 public void setTrace(BindingTrace trace) {
076 this.trace = trace;
077 }
078
079 @Inject
080 public void setSignatureResolver(JavaSignatureResolver signatureResolver) {
081 this.signatureResolver = signatureResolver;
082 }
083
084 @Inject
085 public void setParameterResolver(JavaValueParameterResolver parameterResolver) {
086 this.parameterResolver = parameterResolver;
087 }
088
089 @Inject
090 public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) {
091 this.annotationResolver = annotationResolver;
092 }
093
094 @Nullable
095 SimpleFunctionDescriptor resolveFunctionMutely(
096 @NotNull PsiMethodWrapper method,
097 @NotNull ClassOrNamespaceDescriptor ownerDescriptor
098 ) {
099 PsiClass containingClass = method.getPsiMethod().getContainingClass();
100 assert containingClass != null : "containing class is null for " + method;
101 return resolveMethodToFunctionDescriptor(containingClass, method, DeclarationOrigin.JAVA, ownerDescriptor, false);
102 }
103
104 @Nullable
105 private SimpleFunctionDescriptor resolveMethodToFunctionDescriptor(
106 @NotNull PsiClass psiClass, PsiMethodWrapper method,
107 @NotNull DeclarationOrigin declarationOrigin, @NotNull ClassOrNamespaceDescriptor ownerDescriptor, boolean record
108 ) {
109 if (!DescriptorResolverUtils.isCorrectOwnerForEnumMember(ownerDescriptor, method.getPsiMember())) {
110 return null;
111 }
112
113 PsiType returnPsiType = method.getReturnType();
114 if (returnPsiType == null) {
115 return null;
116 }
117
118 // TODO: ugly
119 if (method.getJetMethodAnnotation().hasPropertyFlag()) {
120 return null;
121 }
122
123 PsiMethod psiMethod = method.getPsiMethod();
124 PsiClass containingClass = psiMethod.getContainingClass();
125 if (declarationOrigin == KOTLIN) {
126 // TODO: unless maybe class explicitly extends Object
127 assert containingClass != null;
128 String ownerClassName = containingClass.getQualifiedName();
129 if (DescriptorResolverUtils.OBJECT_FQ_NAME.asString().equals(ownerClassName)) {
130 return null;
131 }
132 }
133
134 if (trace.get(BindingContext.FUNCTION, psiMethod) != null) {
135 return trace.get(BindingContext.FUNCTION, psiMethod);
136 }
137
138 SimpleFunctionDescriptorImpl functionDescriptorImpl = new SimpleFunctionDescriptorImpl(
139 ownerDescriptor,
140 annotationResolver.resolveAnnotations(psiMethod),
141 Name.identifier(method.getName()),
142 DescriptorKindUtils.flagsToKind(method.getJetMethodAnnotation().kind())
143 );
144
145 String context = "method " + method.getName() + " in class " + psiClass.getQualifiedName();
146
147 List<TypeParameterDescriptor> methodTypeParameters =
148 signatureResolver.resolveMethodTypeParameters(method,
149 functionDescriptorImpl);
150
151 TypeVariableResolver methodTypeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters(methodTypeParameters,
152 functionDescriptorImpl,
153 context);
154
155 JavaDescriptorResolver.ValueParameterDescriptors valueParameterDescriptors = parameterResolver
156 .resolveParameterDescriptors(functionDescriptorImpl, method.getParameters(), methodTypeVariableResolver);
157 JetType returnType = makeReturnType(returnPsiType, method, methodTypeVariableResolver);
158
159 List<String> signatureErrors = Lists.newArrayList();
160
161 List<FunctionDescriptor> superFunctions;
162 if (ownerDescriptor instanceof ClassDescriptor && !method.getJetMethodAnnotation().isDefined()) { // don't propagate for Kotlin functions
163 SignaturesPropagationData signaturesPropagationData = new SignaturesPropagationData(
164 (ClassDescriptor) ownerDescriptor, returnType, valueParameterDescriptors, methodTypeParameters, method, trace);
165 superFunctions = signaturesPropagationData.getSuperFunctions();
166
167 returnType = signaturesPropagationData.getModifiedReturnType();
168 valueParameterDescriptors = signaturesPropagationData.getModifiedValueParameters();
169 methodTypeParameters = signaturesPropagationData.getModifiedTypeParameters();
170
171 signatureErrors.addAll(signaturesPropagationData.getSignatureErrors());
172 }
173 else {
174 superFunctions = Collections.emptyList();
175 }
176
177 AlternativeMethodSignatureData alternativeMethodSignatureData =
178 new AlternativeMethodSignatureData(method, valueParameterDescriptors, returnType, methodTypeParameters,
179 !superFunctions.isEmpty());
180 if (alternativeMethodSignatureData.isAnnotated() && !alternativeMethodSignatureData.hasErrors()) {
181 valueParameterDescriptors = alternativeMethodSignatureData.getValueParameters();
182 returnType = alternativeMethodSignatureData.getReturnType();
183 methodTypeParameters = alternativeMethodSignatureData.getTypeParameters();
184 }
185 else if (alternativeMethodSignatureData.hasErrors()) {
186 signatureErrors.add(alternativeMethodSignatureData.getError());
187 }
188
189 functionDescriptorImpl.initialize(
190 valueParameterDescriptors.getReceiverType(),
191 DescriptorUtils.getExpectedThisObjectIfNeeded(ownerDescriptor),
192 methodTypeParameters,
193 valueParameterDescriptors.getDescriptors(),
194 returnType,
195 DescriptorResolverUtils.resolveModality(method, method.isFinal()),
196 DescriptorResolverUtils.resolveVisibility(psiMethod, method.getJetMethodAnnotation()),
197 /*isInline = */ false
198 );
199
200 if (functionDescriptorImpl.getKind() == CallableMemberDescriptor.Kind.DECLARATION && record) {
201 BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, psiMethod, functionDescriptorImpl);
202 }
203
204 if (declarationOrigin == JAVA && record) {
205 trace.record(JavaBindingContext.IS_DECLARED_IN_JAVA, functionDescriptorImpl);
206 }
207
208 if (containingClass != psiClass && !method.isStatic()) {
209 throw new IllegalStateException("non-static method in subclass");
210 }
211
212 if (!RawTypesCheck.hasRawTypesInHierarchicalSignature(psiMethod)
213 && JavaMethodSignatureUtil.isMethodReturnTypeCompatible(psiMethod)
214 && !containsErrorType(superFunctions, functionDescriptorImpl)) {
215 if (signatureErrors.isEmpty()) {
216 checkFunctionsOverrideCorrectly(method, superFunctions, functionDescriptorImpl);
217 }
218 else {
219 if (record) {
220 trace.record(JavaBindingContext.LOAD_FROM_JAVA_SIGNATURE_ERRORS, functionDescriptorImpl, signatureErrors);
221 }
222 }
223 }
224
225 return functionDescriptorImpl;
226 }
227
228 private static void checkFunctionsOverrideCorrectly(
229 PsiMethodWrapper method,
230 List<FunctionDescriptor> superFunctions,
231 FunctionDescriptor functionDescriptor
232 ) {
233 for (FunctionDescriptor superFunction : superFunctions) {
234 ClassDescriptor klass = (ClassDescriptor) functionDescriptor.getContainingDeclaration();
235 List<TypeSubstitution> substitutions = Lists.newArrayList();
236 while (true) {
237 substitutions.add(SubstitutionUtils.buildDeepSubstitutor(klass.getDefaultType()).getSubstitution());
238 if (!klass.isInner()) {
239 break;
240 }
241 klass = (ClassDescriptor) klass.getContainingDeclaration();
242 }
243 TypeSubstitutor substitutor = TypeSubstitutor.create(substitutions.toArray(new TypeSubstitution[substitutions.size()]));
244 FunctionDescriptor superFunctionSubstituted = superFunction.substitute(substitutor);
245
246 assert superFunctionSubstituted != null :
247 "Couldn't substitute super function: " + superFunction + ", substitutor = " + substitutor;
248
249 OverrideCompatibilityInfo.Result overridableResult =
250 isOverridableBy(superFunctionSubstituted, functionDescriptor).getResult();
251 boolean paramsOk = overridableResult == OverrideCompatibilityInfo.Result.OVERRIDABLE;
252 boolean returnTypeOk =
253 isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, superFunctionSubstituted, functionDescriptor);
254 if (!paramsOk || !returnTypeOk) {
255 LOG.error("Loaded Java method overrides another, but resolved as Kotlin function, doesn't.\n"
256 + "super function = " + superFunction + "\n"
257 + "super class = " + superFunction.getContainingDeclaration() + "\n"
258 + "sub function = " + functionDescriptor + "\n"
259 + "sub class = " + functionDescriptor.getContainingDeclaration() + "\n"
260 + "sub method = " + PsiFormatUtil.getExternalName(method.getPsiMethod()) + "\n"
261 + "@KotlinSignature = " + method.getSignatureAnnotation().signature());
262 }
263 }
264 }
265
266 @NotNull
267 private Set<FunctionDescriptor> resolveNamedGroupFunctions(
268 @NotNull ClassOrNamespaceDescriptor owner, @NotNull PsiClass psiClass,
269 NamedMembers namedMembers, Name methodName, PsiDeclarationProvider scopeData
270 ) {
271
272 Set<SimpleFunctionDescriptor> functionsFromSupertypes = null;
273 if (owner instanceof ClassDescriptor) {
274 functionsFromSupertypes = getFunctionsFromSupertypes(methodName, owner);
275 }
276
277 Set<SimpleFunctionDescriptor> functionsFromCurrent = Sets.newHashSet();
278 for (PsiMethodWrapper method : namedMembers.getMethods()) {
279 SimpleFunctionDescriptor function = resolveMethodToFunctionDescriptor(psiClass, method, scopeData.getDeclarationOrigin(), owner, true);
280 if (function != null) {
281 functionsFromCurrent.add(function);
282
283 if (!DescriptorResolverUtils.isKotlinClass(psiClass)) {
284 ContainerUtil.addIfNotNull(functionsFromCurrent, resolveSamAdapter(function));
285 }
286 }
287 }
288
289 if (owner instanceof NamespaceDescriptor) {
290 ContainerUtil.addIfNotNull(functionsFromCurrent, resolveSamConstructor((NamespaceDescriptor) owner, namedMembers));
291 }
292
293
294 final Set<FunctionDescriptor> fakeOverrides = new HashSet<FunctionDescriptor>();
295 if (owner instanceof ClassDescriptor) {
296 ClassDescriptor classDescriptor = (ClassDescriptor) owner;
297
298 OverrideResolver.generateOverridesInFunctionGroup(methodName, functionsFromSupertypes, functionsFromCurrent, classDescriptor,
299 new OverrideResolver.DescriptorSink() {
300 @Override
301 public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
302 fakeOverrides.add((FunctionDescriptor) fakeOverride);
303 }
304
305 @Override
306 public void conflict(
307 @NotNull CallableMemberDescriptor fromSuper,
308 @NotNull CallableMemberDescriptor fromCurrent
309 ) {
310 // nop
311 }
312 });
313 }
314
315 OverrideResolver.resolveUnknownVisibilities(fakeOverrides, trace);
316
317 Set<FunctionDescriptor> functions = Sets.newHashSet(fakeOverrides);
318 if (isEnumClassObject(owner)) {
319 for (FunctionDescriptor functionDescriptor : functionsFromCurrent) {
320 if (!(isEnumValueOfMethod(functionDescriptor) || isEnumValuesMethod(functionDescriptor))) {
321 functions.add(functionDescriptor);
322 }
323 }
324 }
325 else {
326 functions.addAll(functionsFromCurrent);
327 }
328
329 return functions;
330 }
331
332 @Nullable
333 private static ClassDescriptorFromJvmBytecode findClassInScope(@NotNull JetScope memberScope, @NotNull Name name) {
334 ClassifierDescriptor classifier = memberScope.getClassifier(name);
335 if (classifier instanceof ClassDescriptorFromJvmBytecode) {
336 return (ClassDescriptorFromJvmBytecode) classifier;
337 }
338 return null;
339 }
340
341 // E.g. we have foo.Bar.Baz class declared in Java. It will produce the following descriptors structure:
342 // namespace foo
343 // +-- class Bar
344 // | +-- class Baz
345 // +-- namespace Bar
346 // We need to find class 'Baz' in namespace 'foo.Bar'.
347 @Nullable
348 private static ClassDescriptorFromJvmBytecode findClassInNamespace(@NotNull NamespaceDescriptor namespace, @NotNull Name name) {
349 // First, try to find in namespace directly
350 ClassDescriptorFromJvmBytecode found = findClassInScope(namespace.getMemberScope(), name);
351 if (found != null) {
352 return found;
353 }
354
355 // If unsuccessful, try to find class of the same name as current (class 'foo.Bar')
356 NamespaceDescriptorParent parent = namespace.getContainingDeclaration();
357 if (parent instanceof NamespaceDescriptor) {
358 // Calling recursively, looking for 'Bar' in 'foo'
359 ClassDescriptor classForCurrentNamespace = findClassInNamespace((NamespaceDescriptor) parent, namespace.getName());
360 if (classForCurrentNamespace == null) {
361 return null;
362 }
363
364 // Try to find nested class 'Baz' in class 'foo.Bar'
365 return findClassInScope(DescriptorUtils.getStaticNestedClassesScope(classForCurrentNamespace), name);
366 }
367 return null;
368 }
369
370 @Nullable
371 private SimpleFunctionDescriptor resolveSamConstructor(
372 @NotNull NamespaceDescriptor ownerDescriptor,
373 @NotNull NamedMembers namedMembers
374 ) {
375 PsiClass samInterface = namedMembers.getSamInterface();
376 if (samInterface != null) {
377 ClassDescriptorFromJvmBytecode klass = findClassInNamespace(ownerDescriptor, namedMembers.getName());
378 if (klass != null) {
379 return recordSamConstructor(klass, createSamConstructorFunction(ownerDescriptor, klass), trace);
380 }
381 }
382 return null;
383 }
384
385 @Nullable
386 private SimpleFunctionDescriptor resolveSamAdapter(@NotNull SimpleFunctionDescriptor original) {
387 return isSamAdapterNecessary(original)
388 ? recordSamAdapter(original, createSamAdapterFunction(original), trace)
389 : null;
390 }
391
392 @NotNull
393 public Set<FunctionDescriptor> resolveFunctionGroup(
394 @NotNull Name methodName,
395 @NotNull ClassPsiDeclarationProvider scopeData,
396 @NotNull ClassOrNamespaceDescriptor ownerDescriptor
397 ) {
398
399 NamedMembers namedMembers = scopeData.getMembersCache().get(methodName);
400 if (namedMembers == null) {
401 return Collections.emptySet();
402 }
403 PsiClass psiClass = scopeData.getPsiClass();
404 return resolveNamedGroupFunctions(ownerDescriptor, psiClass, namedMembers, methodName, scopeData);
405 }
406
407 @NotNull
408 public Set<FunctionDescriptor> resolveFunctionGroup(
409 @NotNull Name functionName,
410 @NotNull PackagePsiDeclarationProvider scopeData,
411 @NotNull NamespaceDescriptor ownerDescriptor
412 ) {
413 NamedMembers namedMembers = scopeData.getMembersCache().get(functionName);
414 if (namedMembers != null) {
415 SimpleFunctionDescriptor samConstructor = resolveSamConstructor(ownerDescriptor, namedMembers);
416 if (samConstructor != null) {
417 return Collections.<FunctionDescriptor>singleton(samConstructor);
418 }
419 }
420 return Collections.emptySet();
421 }
422
423 @NotNull
424 private JetType makeReturnType(
425 PsiType returnType, PsiMethodWrapper method,
426 @NotNull TypeVariableResolver typeVariableResolver
427 ) {
428
429 String returnTypeFromAnnotation = method.getJetMethodAnnotation().returnType();
430
431 JetType transformedType;
432 if (returnTypeFromAnnotation.length() > 0) {
433 transformedType = typeTransformer.transformToType(returnTypeFromAnnotation, typeVariableResolver);
434 }
435 else {
436 TypeUsage typeUsage = JavaTypeTransformer.adjustTypeUsageWithMutabilityAnnotations(method.getPsiMethod(), TypeUsage.MEMBER_SIGNATURE_COVARIANT);
437 transformedType = typeTransformer.transformToType(returnType, typeUsage, typeVariableResolver);
438 }
439
440 if (JavaAnnotationResolver.findAnnotationWithExternal(method.getPsiMethod(), JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().asString()) !=
441 null) {
442 return TypeUtils.makeNullableAsSpecified(transformedType, false);
443 }
444 else {
445 return transformedType;
446 }
447 }
448
449 @NotNull
450 private static Set<SimpleFunctionDescriptor> getFunctionsFromSupertypes(
451 @NotNull Name methodName, @NotNull ClassOrNamespaceDescriptor classOrNamespaceDescriptor
452 ) {
453 Set<SimpleFunctionDescriptor> r = Sets.newLinkedHashSet();
454 for (JetType supertype : DescriptorResolverUtils.getSupertypes(classOrNamespaceDescriptor)) {
455 for (FunctionDescriptor function : supertype.getMemberScope().getFunctions(methodName)) {
456 r.add((SimpleFunctionDescriptor) function);
457 }
458 }
459 return r;
460 }
461
462 private static boolean containsErrorType(@NotNull List<FunctionDescriptor> superFunctions, @NotNull FunctionDescriptor function) {
463 if (containsErrorType(function)) {
464 return true;
465 }
466
467 for (FunctionDescriptor superFunction : superFunctions) {
468 if (containsErrorType(superFunction)) {
469 return true;
470 }
471 }
472
473 return false;
474 }
475
476 private static boolean containsErrorType(@NotNull FunctionDescriptor function) {
477 if (ErrorUtils.containsErrorType(function.getReturnType())) {
478 return true;
479 }
480 for (ValueParameterDescriptor parameter : function.getValueParameters()) {
481 if (ErrorUtils.containsErrorType(parameter.getType())) {
482 return true;
483 }
484 }
485 for (TypeParameterDescriptor parameter : function.getTypeParameters()) {
486 for (JetType upperBound : parameter.getUpperBounds()) {
487 if (ErrorUtils.containsErrorType(upperBound)) {
488 return true;
489 }
490 }
491 }
492
493 return false;
494 }
495
496 private static SimpleFunctionDescriptor recordSamConstructor(ClassDescriptorFromJvmBytecode klass, SimpleFunctionDescriptor constructorFunction, BindingTrace trace) {
497 trace.record(JavaBindingContext.SAM_CONSTRUCTOR_TO_INTERFACE, constructorFunction, klass);
498 trace.record(BindingContext.SOURCE_DESCRIPTOR_FOR_SYNTHESIZED, constructorFunction, klass);
499 return constructorFunction;
500 }
501
502 static <F extends FunctionDescriptor> F recordSamAdapter(F original, F adapterFunction, BindingTrace trace) {
503 trace.record(JavaBindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, adapterFunction, original);
504 trace.record(BindingContext.SOURCE_DESCRIPTOR_FOR_SYNTHESIZED, adapterFunction, original);
505 return adapterFunction;
506 }
507 }