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 017package org.jetbrains.jet.lang.resolve.java; 018 019import com.intellij.psi.*; 020import com.intellij.psi.util.PsiFormatUtil; 021import org.jetbrains.annotations.NotNull; 022import org.jetbrains.annotations.Nullable; 023import org.jetbrains.jet.lang.descriptors.*; 024import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 025import org.jetbrains.jet.lang.resolve.constants.StringValue; 026import org.jetbrains.jet.lang.resolve.java.kt.PsiAnnotationWithFlags; 027import org.jetbrains.jet.lang.resolve.java.wrapper.PsiClassWrapper; 028import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMemberWrapper; 029import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper; 030import org.jetbrains.jet.lang.resolve.name.FqName; 031import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; 032import org.jetbrains.jet.lang.resolve.name.Name; 033import org.jetbrains.jet.lang.types.JetType; 034 035import java.util.Collection; 036import java.util.Collections; 037import java.util.List; 038 039import static com.intellij.psi.util.PsiFormatUtilBase.*; 040import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getClassObjectName; 041import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isEnumClassObject; 042 043public 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}