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;
018
019 import com.intellij.psi.*;
020 import com.intellij.psi.util.PsiFormatUtil;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.jet.lang.descriptors.*;
024 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
025 import org.jetbrains.jet.lang.resolve.constants.StringValue;
026 import org.jetbrains.jet.lang.resolve.java.kt.PsiAnnotationWithFlags;
027 import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper;
028 import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMemberWrapper;
029 import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
030 import org.jetbrains.jet.lang.resolve.name.FqName;
031 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
032 import org.jetbrains.jet.lang.resolve.name.Name;
033 import org.jetbrains.jet.lang.types.JetType;
034
035 import java.util.Collection;
036 import java.util.Collections;
037 import java.util.List;
038
039 import static com.intellij.psi.util.PsiFormatUtilBase.*;
040 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName;
041 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumClassObject;
042
043 public final class DescriptorResolverUtils {
044 public static final FqName OBJECT_FQ_NAME = new FqName("java.lang.Object");
045
046 private DescriptorResolverUtils() {
047 }
048
049 public static boolean isKotlinClass(@NotNull PsiClass psiClass) {
050 PsiClassWrapper wrapper = new PsiClassWrapper(psiClass);
051 return wrapper.getJetClass().isDefined() || wrapper.getJetPackageClass().isDefined();
052 }
053
054 @NotNull
055 public static Collection<JetType> getSupertypes(@NotNull ClassOrNamespaceDescriptor classOrNamespaceDescriptor) {
056 if (classOrNamespaceDescriptor instanceof ClassDescriptor) {
057 return ((ClassDescriptor) classOrNamespaceDescriptor).getTypeConstructor().getSupertypes();
058 }
059 return Collections.emptyList();
060 }
061
062 public static Modality resolveModality(PsiMemberWrapper memberWrapper, boolean isFinal) {
063 if (memberWrapper instanceof PsiMethodWrapper) {
064 PsiMethodWrapper method = (PsiMethodWrapper) memberWrapper;
065 if (method.getJetMethodAnnotation().hasForceOpenFlag()) {
066 return Modality.OPEN;
067 }
068 if (method.getJetMethodAnnotation().hasForceFinalFlag()) {
069 return Modality.FINAL;
070 }
071 }
072
073 return Modality.convertFromFlags(memberWrapper.isAbstract(), !isFinal);
074 }
075
076 public static Visibility resolveVisibility(
077 @NotNull PsiModifierListOwner modifierListOwner,
078 @Nullable PsiAnnotationWithFlags annotation
079 ) {
080 if (annotation != null) {
081 if (annotation.hasPrivateFlag()) {
082 return Visibilities.PRIVATE;
083 }
084 else if (annotation.hasInternalFlag()) {
085 return Visibilities.INTERNAL;
086 }
087 else if (annotation.hasProtectedFlag()) {
088 return Visibilities.PROTECTED;
089 }
090 }
091
092 if (modifierListOwner.hasModifierProperty(PsiModifier.PUBLIC)) {
093 return Visibilities.PUBLIC;
094 }
095 if (modifierListOwner.hasModifierProperty(PsiModifier.PRIVATE)) {
096 return Visibilities.PRIVATE;
097 }
098 if (modifierListOwner.hasModifierProperty(PsiModifier.PROTECTED)) {
099 if (modifierListOwner.hasModifierProperty(PsiModifier.STATIC)) {
100 return JavaDescriptorResolver.PROTECTED_STATIC_VISIBILITY;
101 }
102 return JavaDescriptorResolver.PROTECTED_AND_PACKAGE;
103 }
104 return JavaDescriptorResolver.PACKAGE_VISIBILITY;
105 }
106
107 @Nullable
108 public static ValueParameterDescriptor getValueParameterDescriptorForAnnotationParameter(
109 Name argumentName,
110 ClassDescriptor classDescriptor
111 ) {
112 Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
113 assert constructors.size() == 1 : "Annotation class descriptor must have only one constructor";
114 List<ValueParameterDescriptor> valueParameters = constructors.iterator().next().getValueParameters();
115
116 for (ValueParameterDescriptor parameter : valueParameters) {
117 Name parameterName = parameter.getName();
118 if (parameterName.equals(argumentName)) {
119 return parameter;
120 }
121 }
122 return null;
123 }
124
125 public static Visibility getConstructorVisibility(ClassDescriptor classDescriptor) {
126 Visibility containingClassVisibility = classDescriptor.getVisibility();
127 if (containingClassVisibility == JavaDescriptorResolver.PROTECTED_STATIC_VISIBILITY) {
128 return JavaDescriptorResolver.PROTECTED_AND_PACKAGE;
129 }
130 return containingClassVisibility;
131 }
132
133 public static void checkPsiClassIsNotJet(@Nullable PsiClass psiClass) {
134 if (psiClass instanceof JetJavaMirrorMarker) {
135 throw new IllegalStateException("trying to resolve fake jet PsiClass as regular PsiClass: " + psiClass.getQualifiedName());
136 }
137 }
138
139 @NotNull
140 public static FqNameUnsafe getFqNameForClassObject(@NotNull PsiClass psiClass) {
141 String psiClassQualifiedName = psiClass.getQualifiedName();
142 assert psiClassQualifiedName != null : "Reading java class with no qualified name";
143 return new FqNameUnsafe(psiClassQualifiedName + "." + getClassObjectName(psiClass.getName()).asString());
144 }
145
146 @NotNull
147 public static AnnotationDescriptor getAnnotationDescriptorForJavaLangDeprecated(ClassDescriptor classDescriptor) {
148 AnnotationDescriptor annotationDescriptor = new AnnotationDescriptor();
149 annotationDescriptor.setAnnotationType(classDescriptor.getDefaultType());
150 ValueParameterDescriptor value = getValueParameterDescriptorForAnnotationParameter(Name.identifier("value"), classDescriptor);
151 assert value != null : "jet.deprecated must have one parameter called value";
152 annotationDescriptor.setValueArgument(value, new StringValue("Deprecated in Java"));
153 return annotationDescriptor;
154 }
155
156 /**
157 * @return true if {@code member} is a static member of enum class, which is to be put into its class object (and not into the
158 * corresponding package). This applies to enum entries, values() and valueOf(String) methods
159 */
160 public static boolean shouldBeInEnumClassObject(@NotNull PsiMember member) {
161 PsiClass psiClass = member.getContainingClass();
162 if (psiClass == null || !psiClass.isEnum()) return false;
163
164 if (member instanceof PsiEnumConstant) return true;
165
166 if (!(member instanceof PsiMethod)) return false;
167 String signature = PsiFormatUtil.formatMethod((PsiMethod) member,
168 PsiSubstitutor.EMPTY, SHOW_NAME | SHOW_PARAMETERS, SHOW_TYPE | SHOW_FQ_CLASS_NAMES);
169
170 return "values()".equals(signature) ||
171 "valueOf(java.lang.String)".equals(signature);
172 }
173
174 public static boolean isCorrectOwnerForEnumMember(
175 @NotNull ClassOrNamespaceDescriptor ownerDescriptor,
176 @NotNull PsiMember member
177 ) {
178 return isEnumClassObject(ownerDescriptor) == shouldBeInEnumClassObject(member);
179 }
180 }