From 88bd991729660df00a9a71b9d3995c3e96639add Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Sat, 6 Oct 2012 19:08:57 +0400 Subject: [PATCH] Extract FunctionResolver and AnnotationResolver classes from JavaDescriptorResolver --- .../resolve/java/JavaDescriptorResolver.java | 211 +++--------------- .../lang/resolve/java/PsiClassFinderImpl.java | 5 +- .../resolve/java/kt/JetClassAnnotation.java | 4 +- .../java/kt/JetConstructorAnnotation.java | 4 +- .../resolve/java/kt/JetMethodAnnotation.java | 4 +- .../java/kt/JetTypeParameterAnnotation.java | 4 +- .../java/kt/JetValueParameterAnnotation.java | 4 +- .../java/kt/KotlinSignatureAnnotation.java | 4 +- .../java/resolver/AnnotationResolver.java | 145 ++++++++++++ .../java/resolver/FunctionResolver.java | 138 ++++++++++++ .../java/resolver/PropertiesResolver.java | 4 +- .../ktSignature/KotlinSignatureUtil.java | 4 +- 12 files changed, 329 insertions(+), 202 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationResolver.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FunctionResolver.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 7bcd70358be..8a565f00bf0 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -19,7 +19,6 @@ package org.jetbrains.jet.lang.resolve.java; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.intellij.codeInsight.ExternalAnnotationsManager; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import gnu.trove.THashMap; @@ -29,21 +28,18 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.*; -import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.OverrideResolver; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.ResolverClassData; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.ResolverNamespaceData; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.ResolverScopeData; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData.ResolverSyntheticClassObjectClassData; import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode; import org.jetbrains.jet.lang.resolve.java.descriptor.JavaNamespaceDescriptor; -import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSignatureData; -import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils; import org.jetbrains.jet.lang.resolve.java.kt.PsiAnnotationWithFlags; -import org.jetbrains.jet.lang.resolve.java.resolver.ClassResolver; -import org.jetbrains.jet.lang.resolve.java.resolver.CompileTimeConstResolver; -import org.jetbrains.jet.lang.resolve.java.resolver.ConstructorResolver; -import org.jetbrains.jet.lang.resolve.java.resolver.PropertiesResolver; +import org.jetbrains.jet.lang.resolve.java.resolver.*; import org.jetbrains.jet.lang.resolve.java.scope.JavaClassMembersScope; import org.jetbrains.jet.lang.resolve.java.scope.JavaPackageScope; import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper; @@ -81,7 +77,7 @@ import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName; */ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameResolver { - private static final FqName OBJECT_FQ_NAME = new FqName("java.lang.Object"); + public static final FqName OBJECT_FQ_NAME = new FqName("java.lang.Object"); public static final Name JAVA_ROOT = Name.special(""); @@ -131,6 +127,8 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes private final ClassResolver classResolver = new ClassResolver(this); private final ConstructorResolver constructorResolver = new ConstructorResolver(this); private final CompileTimeConstResolver compileTimeConstResolver = new CompileTimeConstResolver(this); + private final AnnotationResolver annotationResolver = new AnnotationResolver(this); + private final FunctionResolver functionResolver = new FunctionResolver(this); @Inject public void setProject(Project project) { @@ -210,6 +208,14 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes return classResolver; } + public CompileTimeConstResolver getCompileTimeConstResolver() { + return compileTimeConstResolver; + } + + public AnnotationResolver getAnnotationResolver() { + return annotationResolver; + } + public static void checkPsiClassIsNotJet(PsiClass psiClass) { if (psiClass instanceof JetJavaMirrorMarker) { throw new IllegalStateException("trying to resolve fake jet PsiClass as regular PsiClass: " + psiClass.getQualifiedName()); @@ -676,7 +682,8 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes else { JetType transformedType; - if (findAnnotation(parameter.getPsiParameter(), JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName()) != null) { + if (AnnotationResolver + .findAnnotation(parameter.getPsiParameter(), JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName()) != null) { transformedType = TypeUtils.makeNullableAsSpecified(outType, false); } else { @@ -747,7 +754,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes Set functionsFromCurrent = Sets.newHashSet(); for (PsiMethodWrapper method : namedMembers.getMethods()) { - SimpleFunctionDescriptor function = resolveMethodToFunctionDescriptor(psiClass, method, scopeData); + SimpleFunctionDescriptor function = functionResolver.resolveMethodToFunctionDescriptor(psiClass, method, scopeData); if (function != null) { functionsFromCurrent.add(function); } @@ -849,91 +856,6 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes return new ValueParameterDescriptors(receiverType, result); } - @Nullable - private SimpleFunctionDescriptor resolveMethodToFunctionDescriptor( - @NotNull final PsiClass psiClass, final PsiMethodWrapper method, - @NotNull ResolverScopeData scopeData) { - - getResolverScopeData(scopeData); - - PsiType returnPsiType = method.getReturnType(); - if (returnPsiType == null) { - return null; - } - - // TODO: ugly - if (method.getJetMethod().hasPropertyFlag()) { - return null; - } - - final PsiMethod psiMethod = method.getPsiMethod(); - final PsiClass containingClass = psiMethod.getContainingClass(); - if (scopeData.isKotlin()) { - // TODO: unless maybe class explicitly extends Object - assert containingClass != null; - String ownerClassName = containingClass.getQualifiedName(); - if (OBJECT_FQ_NAME.getFqName().equals(ownerClassName)) { - return null; - } - } - - if (trace.get(BindingContext.FUNCTION, psiMethod) != null) { - return trace.get(BindingContext.FUNCTION, psiMethod); - } - - SimpleFunctionDescriptorImpl functionDescriptorImpl = new SimpleFunctionDescriptorImpl( - scopeData.getClassOrNamespaceDescriptor(), - resolveAnnotations(psiMethod), - Name.identifier(method.getName()), - DescriptorKindUtils.flagsToKind(method.getJetMethod().kind()) - ); - - String context = "method " + method.getName() + " in class " + psiClass.getQualifiedName(); - - List methodTypeParameters = javaDescriptorSignatureResolver.resolveMethodTypeParameters(method, - functionDescriptorImpl); - - TypeVariableResolver methodTypeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters(methodTypeParameters, - functionDescriptorImpl, - context); - - - ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(functionDescriptorImpl, method.getParameters(), methodTypeVariableResolver); - JetType returnType = makeReturnType(returnPsiType, method, methodTypeVariableResolver); - - // TODO consider better place for this check - AlternativeMethodSignatureData alternativeMethodSignatureData = - new AlternativeMethodSignatureData(method, valueParameterDescriptors, returnType, methodTypeParameters); - if (alternativeMethodSignatureData.isAnnotated() && !alternativeMethodSignatureData.hasErrors()) { - valueParameterDescriptors = alternativeMethodSignatureData.getValueParameters(); - returnType = alternativeMethodSignatureData.getReturnType(); - methodTypeParameters = alternativeMethodSignatureData.getTypeParameters(); - } - else if (alternativeMethodSignatureData.hasErrors()) { - trace.record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, functionDescriptorImpl, alternativeMethodSignatureData.getError()); - } - - functionDescriptorImpl.initialize( - valueParameterDescriptors.receiverType, - DescriptorUtils.getExpectedThisObjectIfNeeded(scopeData.getClassOrNamespaceDescriptor()), - methodTypeParameters, - valueParameterDescriptors.descriptors, - returnType, - resolveModality(method, method.isFinal()), - resolveVisibility(psiMethod, method.getJetMethod()), - /*isInline = */ false - ); - - if (functionDescriptorImpl.getKind() == CallableMemberDescriptor.Kind.DECLARATION) { - BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, psiMethod, functionDescriptorImpl); - } - - if (containingClass != psiClass && !method.isStatic()) { - throw new IllegalStateException("non-static method in subclass"); - } - return functionDescriptorImpl; - } - private static boolean isEnumSpecialMethod(@NotNull FunctionDescriptor functionDescriptor) { List methodTypeParameters = functionDescriptor.getValueParameters(); String methodName = functionDescriptor.getName().getName(); @@ -946,71 +868,20 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes } public List resolveAnnotations(PsiModifierListOwner owner, @NotNull List tasks) { - PsiAnnotation[] psiAnnotations = getAllAnnotations(owner); - List r = Lists.newArrayListWithCapacity(psiAnnotations.length); - for (PsiAnnotation psiAnnotation : psiAnnotations) { - AnnotationDescriptor annotation = resolveAnnotation(psiAnnotation, tasks); - if (annotation != null) { - r.add(annotation); - } - } - return r; + return annotationResolver.resolveAnnotations(owner, tasks); } public List resolveAnnotations(PsiModifierListOwner owner) { - List tasks = Lists.newArrayList(); - List annotations = resolveAnnotations(owner, tasks); - for (Runnable task : tasks) { - task.run(); - } - return annotations; + return annotationResolver.resolveAnnotations(owner); } @Nullable public AnnotationDescriptor resolveAnnotation(PsiAnnotation psiAnnotation, @NotNull List taskList) { - final AnnotationDescriptor annotation = new AnnotationDescriptor(); - String qname = psiAnnotation.getQualifiedName(); - if (qname == null) { - return null; - } // Don't process internal jet annotations and jetbrains NotNull annotations - if (qname.startsWith("jet.runtime.typeinfo.") || qname.equals(JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName())) { - return null; - } - - FqName annotationFqName = new FqName(qname); - final ClassDescriptor clazz = classResolver.resolveClass(annotationFqName, DescriptorSearchRule.INCLUDE_KOTLIN, taskList); - if (clazz == null) { - return null; - } - - taskList.add(new Runnable() { - @Override - public void run() { - annotation.setAnnotationType(clazz.getDefaultType()); - } - }); - PsiAnnotationParameterList parameterList = psiAnnotation.getParameterList(); - for (PsiNameValuePair psiNameValuePair : parameterList.getAttributes()) { - PsiAnnotationMemberValue value = psiNameValuePair.getValue(); - String name = psiNameValuePair.getName(); - if (name == null) name = "value"; - Name identifier = Name.identifier(name); - - CompileTimeConstant compileTimeConst = - compileTimeConstResolver.getCompileTimeConstFromExpression(annotationFqName, identifier, value, taskList); - if (compileTimeConst != null) { - ValueParameterDescriptor valueParameterDescriptor = getValueParameterDescriptorForAnnotationParameter(identifier, clazz); - if (valueParameterDescriptor != null) { - annotation.setValueArgument(valueParameterDescriptor, compileTimeConst); - } - } - } - - return annotation; + return annotationResolver.resolveAnnotation(psiAnnotation, taskList); } @Nullable @@ -1060,8 +931,10 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes } } - private JetType makeReturnType(PsiType returnType, PsiMethodWrapper method, - @NotNull TypeVariableResolver typeVariableResolver) { + public JetType makeReturnType( + PsiType returnType, PsiMethodWrapper method, + @NotNull TypeVariableResolver typeVariableResolver + ) { String returnTypeFromAnnotation = method.getJetMethod().returnType(); @@ -1074,7 +947,7 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes returnType, JavaTypeTransformer.TypeUsage.MEMBER_SIGNATURE_COVARIANT, typeVariableResolver); } - if (findAnnotation(method.getPsiMethod(), JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName()) != null) { + if (AnnotationResolver.findAnnotation(method.getPsiMethod(), JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName()) != null) { return TypeUtils.makeNullableAsSpecified(transformedType, false); } else { @@ -1164,34 +1037,4 @@ public class JavaDescriptorResolver implements DependencyClassByQualifiedNameRes assert classDescriptor != null : "Couldn't resolve class " + name; return classDescriptor; } - - @NotNull - public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner) { - List result = new ArrayList(); - - PsiModifierList list = owner.getModifierList(); - if (list != null) { - result.addAll(Arrays.asList(list.getAnnotations())); - } - - PsiAnnotation[] externalAnnotations = ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotations(owner); - if (externalAnnotations != null) { - result.addAll(Arrays.asList(externalAnnotations)); - } - - return result.toArray(new PsiAnnotation[result.size()]); - } - - @Nullable - public static PsiAnnotation findAnnotation(@NotNull PsiModifierListOwner owner, @NotNull String fqName) { - PsiModifierList list = owner.getModifierList(); - if (list != null) { - PsiAnnotation found = list.findAnnotation(fqName); - if (found != null) { - return found; - } - } - - return ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotation(owner, fqName); - } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassFinderImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassFinderImpl.java index 66da45adf44..b7178d7adc2 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassFinderImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassFinderImpl.java @@ -25,6 +25,7 @@ import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationResolver; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.plugin.JetFileType; @@ -80,8 +81,8 @@ public class PsiClassFinderImpl implements PsiClassFinder { } if ("jet".equals(qualifiedName.parent().getFqName())) { - PsiAnnotation assertInvisibleAnnotation = JavaDescriptorResolver - .findAnnotation(original, JvmStdlibNames.ASSERT_INVISIBLE_IN_RESOLVER.getFqName().getFqName()); + PsiAnnotation assertInvisibleAnnotation = + AnnotationResolver.findAnnotation(original, JvmStdlibNames.ASSERT_INVISIBLE_IN_RESOLVER.getFqName().getFqName()); if (assertInvisibleAnnotation != null) { if (runtimeClassesHandleMode == RuntimeClassesHandleMode.IGNORE) { return null; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetClassAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetClassAnnotation.java index 936ba298645..d08dd441801 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetClassAnnotation.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetClassAnnotation.java @@ -20,8 +20,8 @@ import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiClass; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationResolver; /** * @author Stepan Koltsov @@ -56,7 +56,7 @@ public class JetClassAnnotation extends PsiAnnotationWithFlags { @NotNull public static JetClassAnnotation get(PsiClass psiClass) { - final PsiAnnotation annotation = JavaDescriptorResolver.findAnnotation(psiClass, JvmStdlibNames.JET_CLASS.getFqName().getFqName()); + final PsiAnnotation annotation = AnnotationResolver.findAnnotation(psiClass, JvmStdlibNames.JET_CLASS.getFqName().getFqName()); return annotation != null ? new JetClassAnnotation(annotation) : NULL_ANNOTATION; } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetConstructorAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetConstructorAnnotation.java index 5624aeb21aa..6224c1eaddd 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetConstructorAnnotation.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetConstructorAnnotation.java @@ -19,8 +19,8 @@ package org.jetbrains.jet.lang.resolve.java.kt; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiMethod; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationResolver; /** * @author Stepan Koltsov @@ -51,7 +51,7 @@ public class JetConstructorAnnotation extends PsiAnnotationWithFlags { public static JetConstructorAnnotation get(PsiMethod constructor) { final PsiAnnotation annotation = - JavaDescriptorResolver.findAnnotation(constructor, JvmStdlibNames.JET_CONSTRUCTOR.getFqName().getFqName()); + AnnotationResolver.findAnnotation(constructor, JvmStdlibNames.JET_CONSTRUCTOR.getFqName().getFqName()); return annotation != null ? new JetConstructorAnnotation(annotation) : NULL_ANNOTATION; } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetMethodAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetMethodAnnotation.java index dc6ac3bff48..11d005c75f2 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetMethodAnnotation.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetMethodAnnotation.java @@ -20,8 +20,8 @@ import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiMethod; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationResolver; /** * @author Stepan Koltsov @@ -73,7 +73,7 @@ public class JetMethodAnnotation extends PsiAnnotationWithFlags { public static JetMethodAnnotation get(PsiMethod psiMethod) { final PsiAnnotation annotation = - JavaDescriptorResolver.findAnnotation(psiMethod, JvmStdlibNames.JET_METHOD.getFqName().getFqName()); + AnnotationResolver.findAnnotation(psiMethod, JvmStdlibNames.JET_METHOD.getFqName().getFqName()); return annotation != null ? new JetMethodAnnotation(annotation) : NULL_ANNOTATION; } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetTypeParameterAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetTypeParameterAnnotation.java index e1200bb02f2..858f94b87f9 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetTypeParameterAnnotation.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetTypeParameterAnnotation.java @@ -20,8 +20,8 @@ import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiParameter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationResolver; /** * @author Stepan Koltsov @@ -43,7 +43,7 @@ public class JetTypeParameterAnnotation extends PsiAnnotationWrapper { @NotNull public static JetTypeParameterAnnotation get(@NotNull PsiParameter psiParameter) { final PsiAnnotation annotation = - JavaDescriptorResolver.findAnnotation(psiParameter, JvmStdlibNames.JET_TYPE_PARAMETER.getFqName().getFqName()); + AnnotationResolver.findAnnotation(psiParameter, JvmStdlibNames.JET_TYPE_PARAMETER.getFqName().getFqName()); return annotation != null ? new JetTypeParameterAnnotation(annotation) : NULL_ANNOTATION; } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetValueParameterAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetValueParameterAnnotation.java index 27ba2d8c916..49d862414be 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetValueParameterAnnotation.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetValueParameterAnnotation.java @@ -20,8 +20,8 @@ import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiParameter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationResolver; /** * @author Stepan Koltsov @@ -74,7 +74,7 @@ public class JetValueParameterAnnotation extends PsiAnnotationWrapper { public static JetValueParameterAnnotation get(PsiParameter psiParameter) { final PsiAnnotation annotation = - JavaDescriptorResolver.findAnnotation(psiParameter, JvmStdlibNames.JET_VALUE_PARAMETER.getFqName().getFqName()); + AnnotationResolver.findAnnotation(psiParameter, JvmStdlibNames.JET_VALUE_PARAMETER.getFqName().getFqName()); return annotation != null ? new JetValueParameterAnnotation(annotation) : NULL_ANNOTATION; } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/KotlinSignatureAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/KotlinSignatureAnnotation.java index d77db22b9bd..adc438e1f7c 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/KotlinSignatureAnnotation.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/KotlinSignatureAnnotation.java @@ -21,8 +21,8 @@ import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiModifierListOwner; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationResolver; /** * @author Evgeny Gerashchenko @@ -54,7 +54,7 @@ public class KotlinSignatureAnnotation extends PsiAnnotationWrapper { @NotNull public static KotlinSignatureAnnotation get(PsiModifierListOwner psiModifierListOwner) { final PsiAnnotation annotation = - JavaDescriptorResolver.findAnnotation(psiModifierListOwner, JvmStdlibNames.KOTLIN_SIGNATURE.getFqName().getFqName()); + AnnotationResolver.findAnnotation(psiModifierListOwner, JvmStdlibNames.KOTLIN_SIGNATURE.getFqName().getFqName()); return annotation != null ? new KotlinSignatureAnnotation(annotation) : NULL_ANNOTATION; } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationResolver.java new file mode 100644 index 00000000000..fa8685c0a3b --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationResolver.java @@ -0,0 +1,145 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.java.resolver; + +import com.google.common.collect.Lists; +import com.intellij.codeInsight.ExternalAnnotationsManager; +import com.intellij.psi.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; +import org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.name.Name; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class AnnotationResolver { + private final JavaDescriptorResolver javaDescriptorResolver; + + public AnnotationResolver(JavaDescriptorResolver javaDescriptorResolver) { + this.javaDescriptorResolver = javaDescriptorResolver; + } + + public List resolveAnnotations(PsiModifierListOwner owner, @NotNull List tasks) { + PsiAnnotation[] psiAnnotations = getAllAnnotations(owner); + List r = Lists.newArrayListWithCapacity(psiAnnotations.length); + for (PsiAnnotation psiAnnotation : psiAnnotations) { + AnnotationDescriptor annotation = resolveAnnotation(psiAnnotation, tasks); + if (annotation != null) { + r.add(annotation); + } + } + return r; + } + + public List resolveAnnotations(PsiModifierListOwner owner) { + List tasks = Lists.newArrayList(); + List annotations = resolveAnnotations(owner, tasks); + for (Runnable task : tasks) { + task.run(); + } + return annotations; + } + + @Nullable + public AnnotationDescriptor resolveAnnotation(PsiAnnotation psiAnnotation, @NotNull List taskList) { + final AnnotationDescriptor annotation = new AnnotationDescriptor(); + String qname = psiAnnotation.getQualifiedName(); + if (qname == null) { + return null; + } + + // Don't process internal jet annotations and jetbrains NotNull annotations + if (qname.startsWith("jet.runtime.typeinfo.") || qname.equals(JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName())) { + return null; + } + + FqName annotationFqName = new FqName(qname); + final ClassDescriptor clazz = + javaDescriptorResolver.getClassResolver().resolveClass(annotationFqName, DescriptorSearchRule.INCLUDE_KOTLIN, taskList); + if (clazz == null) { + return null; + } + + taskList.add(new Runnable() { + @Override + public void run() { + annotation.setAnnotationType(clazz.getDefaultType()); + } + }); + + + PsiAnnotationParameterList parameterList = psiAnnotation.getParameterList(); + for (PsiNameValuePair psiNameValuePair : parameterList.getAttributes()) { + PsiAnnotationMemberValue value = psiNameValuePair.getValue(); + String name = psiNameValuePair.getName(); + if (name == null) name = "value"; + Name identifier = Name.identifier(name); + + CompileTimeConstant compileTimeConst = + javaDescriptorResolver.getCompileTimeConstResolver() + .getCompileTimeConstFromExpression(annotationFqName, identifier, value, taskList); + if (compileTimeConst != null) { + ValueParameterDescriptor valueParameterDescriptor = + JavaDescriptorResolver.getValueParameterDescriptorForAnnotationParameter(identifier, clazz); + if (valueParameterDescriptor != null) { + annotation.setValueArgument(valueParameterDescriptor, compileTimeConst); + } + } + } + + return annotation; + } + + @NotNull + public static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner) { + List result = new ArrayList(); + + PsiModifierList list = owner.getModifierList(); + if (list != null) { + result.addAll(Arrays.asList(list.getAnnotations())); + } + + PsiAnnotation[] externalAnnotations = ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotations(owner); + if (externalAnnotations != null) { + result.addAll(Arrays.asList(externalAnnotations)); + } + + return result.toArray(new PsiAnnotation[result.size()]); + } + + @Nullable + public static PsiAnnotation findAnnotation(@NotNull PsiModifierListOwner owner, @NotNull String fqName) { + PsiModifierList list = owner.getModifierList(); + if (list != null) { + PsiAnnotation found = list.findAnnotation(fqName); + if (found != null) { + return found; + } + } + + return ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotation(owner, fqName); + } +} \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FunctionResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FunctionResolver.java new file mode 100644 index 00000000000..f085760a0ae --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/FunctionResolver.java @@ -0,0 +1,138 @@ +/* + * Copyright 2010-2012 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.lang.resolve.java.resolver; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; +import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolveData; +import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; +import org.jetbrains.jet.lang.resolve.java.TypeVariableResolver; +import org.jetbrains.jet.lang.resolve.java.TypeVariableResolvers; +import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSignatureData; +import org.jetbrains.jet.lang.resolve.java.kt.DescriptorKindUtils; +import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper; +import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.types.JetType; + +import java.util.List; + +public class FunctionResolver { + private final JavaDescriptorResolver javaDescriptorResolver; + + public FunctionResolver(JavaDescriptorResolver javaDescriptorResolver) { + this.javaDescriptorResolver = javaDescriptorResolver; + } + + @Nullable + public SimpleFunctionDescriptor resolveMethodToFunctionDescriptor( + @NotNull final PsiClass psiClass, final PsiMethodWrapper method, + @NotNull JavaDescriptorResolveData.ResolverScopeData scopeData + ) { + + JavaDescriptorResolver.getResolverScopeData(scopeData); + + PsiType returnPsiType = method.getReturnType(); + if (returnPsiType == null) { + return null; + } + + // TODO: ugly + if (method.getJetMethod().hasPropertyFlag()) { + return null; + } + + final PsiMethod psiMethod = method.getPsiMethod(); + final PsiClass containingClass = psiMethod.getContainingClass(); + if (scopeData.isKotlin()) { + // TODO: unless maybe class explicitly extends Object + assert containingClass != null; + String ownerClassName = containingClass.getQualifiedName(); + if (JavaDescriptorResolver.OBJECT_FQ_NAME.getFqName().equals(ownerClassName)) { + return null; + } + } + + if (javaDescriptorResolver.getTrace().get(BindingContext.FUNCTION, psiMethod) != null) { + return javaDescriptorResolver.getTrace().get(BindingContext.FUNCTION, psiMethod); + } + + SimpleFunctionDescriptorImpl functionDescriptorImpl = new SimpleFunctionDescriptorImpl( + scopeData.getClassOrNamespaceDescriptor(), + javaDescriptorResolver.getAnnotationResolver().resolveAnnotations(psiMethod), + Name.identifier(method.getName()), + DescriptorKindUtils.flagsToKind(method.getJetMethod().kind()) + ); + + String context = "method " + method.getName() + " in class " + psiClass.getQualifiedName(); + + List methodTypeParameters = + javaDescriptorResolver.getJavaDescriptorSignatureResolver().resolveMethodTypeParameters(method, + functionDescriptorImpl); + + TypeVariableResolver methodTypeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters(methodTypeParameters, + functionDescriptorImpl, + context); + + + JavaDescriptorResolver.ValueParameterDescriptors valueParameterDescriptors = javaDescriptorResolver + .resolveParameterDescriptors(functionDescriptorImpl, method.getParameters(), methodTypeVariableResolver); + JetType returnType = javaDescriptorResolver.makeReturnType(returnPsiType, method, methodTypeVariableResolver); + + // TODO consider better place for this check + AlternativeMethodSignatureData alternativeMethodSignatureData = + new AlternativeMethodSignatureData(method, valueParameterDescriptors, returnType, methodTypeParameters); + if (alternativeMethodSignatureData.isAnnotated() && !alternativeMethodSignatureData.hasErrors()) { + valueParameterDescriptors = alternativeMethodSignatureData.getValueParameters(); + returnType = alternativeMethodSignatureData.getReturnType(); + methodTypeParameters = alternativeMethodSignatureData.getTypeParameters(); + } + else if (alternativeMethodSignatureData.hasErrors()) { + javaDescriptorResolver.getTrace().record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, functionDescriptorImpl, + alternativeMethodSignatureData.getError()); + } + + functionDescriptorImpl.initialize( + valueParameterDescriptors.getReceiverType(), + DescriptorUtils.getExpectedThisObjectIfNeeded(scopeData.getClassOrNamespaceDescriptor()), + methodTypeParameters, + valueParameterDescriptors.getDescriptors(), + returnType, + JavaDescriptorResolver.resolveModality(method, method.isFinal()), + JavaDescriptorResolver.resolveVisibility(psiMethod, method.getJetMethod()), + /*isInline = */ false + ); + + if (functionDescriptorImpl.getKind() == CallableMemberDescriptor.Kind.DECLARATION) { + BindingContextUtils.recordFunctionDeclarationToDescriptor(javaDescriptorResolver.getTrace(), psiMethod, functionDescriptorImpl); + } + + if (containingClass != psiClass && !method.isStatic()) { + throw new IllegalStateException("non-static method in subclass"); + } + return functionDescriptorImpl; + } +} \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/PropertiesResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/PropertiesResolver.java index b133e24b3d5..5ba73a4e9f0 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/PropertiesResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/PropertiesResolver.java @@ -292,8 +292,8 @@ public final class PropertiesResolver { } else { propertyType = semanticServices.getTypeTransformer().transformToType(characteristicMember.getType().getPsiType(), typeVariableResolverForPropertyInternals); - if (JavaDescriptorResolver.findAnnotation(characteristicMember.getType().getPsiNotNullOwner(), - JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName()) != null) { + if (AnnotationResolver.findAnnotation(characteristicMember.getType().getPsiNotNullOwner(), + JvmAbi.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().getFqName()) != null) { propertyType = TypeUtils.makeNullableAsSpecified(propertyType, false); } else if (members.getter == null && members.setter == null && members.field.getMember().isFinal() && members.field.getMember().isStatic()) { diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/ktSignature/KotlinSignatureUtil.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/ktSignature/KotlinSignatureUtil.java index 3a32d40646a..36ed68f1b18 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/ktSignature/KotlinSignatureUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/ktSignature/KotlinSignatureUtil.java @@ -26,8 +26,8 @@ import com.intellij.psi.impl.compiled.ClsElementImpl; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; +import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationResolver; /** * @author Evgeny Gerashchenko @@ -84,7 +84,7 @@ class KotlinSignatureUtil { static PsiAnnotation findKotlinSignatureAnnotation(@NotNull PsiElement element) { if (!(element instanceof PsiModifierListOwner)) return null; PsiModifierListOwner annotationOwner = getAnnotationOwner(element); - PsiAnnotation annotation = JavaDescriptorResolver.findAnnotation(annotationOwner, KOTLIN_SIGNATURE_ANNOTATION); + PsiAnnotation annotation = AnnotationResolver.findAnnotation(annotationOwner, KOTLIN_SIGNATURE_ANNOTATION); if (annotation == null) return null; if (annotation.getParameterList().getAttributes().length == 0) return null; return annotation;