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.resolver; 018 019import com.google.common.collect.Lists; 020import com.intellij.psi.*; 021import jet.typeinfo.TypeInfoVariance; 022import org.jetbrains.annotations.NotNull; 023import org.jetbrains.annotations.Nullable; 024import org.jetbrains.jet.lang.descriptors.*; 025import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; 026import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; 027import org.jetbrains.jet.lang.resolve.DescriptorUtils; 028import org.jetbrains.jet.lang.resolve.java.*; 029import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation; 030import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper; 031import org.jetbrains.jet.lang.resolve.name.Name; 032import org.jetbrains.jet.lang.types.JetType; 033import org.jetbrains.jet.lang.types.Variance; 034import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 035import org.jetbrains.jet.rt.signature.JetSignatureAdapter; 036import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; 037import org.jetbrains.jet.rt.signature.JetSignatureReader; 038import org.jetbrains.jet.rt.signature.JetSignatureVisitor; 039 040import javax.inject.Inject; 041import java.util.ArrayList; 042import java.util.Collections; 043import java.util.List; 044 045public final class JavaSignatureResolver { 046 047 @NotNull 048 private JavaSemanticServices semanticServices; 049 050 @Inject 051 public void setJavaSemanticServices(@NotNull JavaSemanticServices javaSemanticServices) { 052 this.semanticServices = javaSemanticServices; 053 } 054 055 private static boolean isJavaLangObject(@NotNull JetType type) { 056 ClassifierDescriptor classifierDescriptor = type.getConstructor().getDeclarationDescriptor(); 057 return classifierDescriptor instanceof ClassDescriptor && 058 DescriptorUtils.getFQName(classifierDescriptor).equalsTo(DescriptorResolverUtils.OBJECT_FQ_NAME); 059 } 060 061 private enum TypeParameterDescriptorOrigin { 062 JAVA, 063 KOTLIN, 064 } 065 066 public static class TypeParameterDescriptorInitialization { 067 @NotNull 068 private final TypeParameterDescriptorOrigin origin; 069 @NotNull 070 private final TypeParameterDescriptorImpl descriptor; 071 private final PsiTypeParameter psiTypeParameter; 072 @Nullable 073 private final List<JetType> upperBoundsForKotlin; 074 075 private TypeParameterDescriptorInitialization(@NotNull TypeParameterDescriptorImpl descriptor, @NotNull PsiTypeParameter psiTypeParameter) { 076 this.origin = TypeParameterDescriptorOrigin.JAVA; 077 this.descriptor = descriptor; 078 this.psiTypeParameter = psiTypeParameter; 079 this.upperBoundsForKotlin = null; 080 } 081 082 private TypeParameterDescriptorInitialization( 083 @NotNull TypeParameterDescriptorImpl descriptor, @NotNull PsiTypeParameter psiTypeParameter, 084 @Nullable List<JetType> upperBoundsForKotlin 085 ) { 086 this.origin = TypeParameterDescriptorOrigin.KOTLIN; 087 this.descriptor = descriptor; 088 this.psiTypeParameter = psiTypeParameter; 089 this.upperBoundsForKotlin = upperBoundsForKotlin; 090 } 091 092 @NotNull 093 public TypeParameterDescriptorImpl getDescriptor() { 094 return descriptor; 095 } 096 } 097 098 099 100 @NotNull 101 private static PsiTypeParameter getPsiTypeParameterByName(PsiTypeParameterListOwner clazz, String name) { 102 for (PsiTypeParameter typeParameter : clazz.getTypeParameters()) { 103 if (typeParameter.getName().equals(name)) { 104 return typeParameter; 105 } 106 } 107 throw new IllegalStateException("PsiTypeParameter '" + name + "' is not found"); 108 } 109 110 111 112 private abstract class JetSignatureTypeParameterVisitor extends JetSignatureExceptionsAdapter { 113 114 @NotNull 115 private final PsiTypeParameterListOwner psiOwner; 116 @NotNull 117 private final String name; 118 @NotNull 119 private final TypeVariableResolver typeVariableResolver; 120 @NotNull 121 private final TypeParameterDescriptorImpl typeParameterDescriptor; 122 123 protected JetSignatureTypeParameterVisitor( 124 @NotNull PsiTypeParameterListOwner psiOwner, 125 @NotNull String name, 126 @NotNull TypeVariableResolver typeVariableResolver, 127 @NotNull TypeParameterDescriptorImpl typeParameterDescriptor) 128 { 129 if (name.isEmpty()) { 130 throw new IllegalStateException(); 131 } 132 133 this.psiOwner = psiOwner; 134 this.name = name; 135 this.typeVariableResolver = typeVariableResolver; 136 this.typeParameterDescriptor = typeParameterDescriptor; 137 } 138 139 List<JetType> upperBounds = new ArrayList<JetType>(); 140 141 @Override 142 public JetSignatureVisitor visitClassBound() { 143 return new JetTypeJetSignatureReader(semanticServices, KotlinBuiltIns.getInstance(), typeVariableResolver) { 144 @Override 145 protected void done(@NotNull JetType jetType) { 146 if (isJavaLangObject(jetType)) { 147 return; 148 } 149 upperBounds.add(jetType); 150 } 151 }; 152 } 153 154 @Override 155 public JetSignatureVisitor visitInterfaceBound() { 156 return new JetTypeJetSignatureReader(semanticServices, KotlinBuiltIns.getInstance(), typeVariableResolver) { 157 @Override 158 protected void done(@NotNull JetType jetType) { 159 upperBounds.add(jetType); 160 } 161 }; 162 } 163 164 @Override 165 public void visitFormalTypeParameterEnd() { 166 PsiTypeParameter psiTypeParameter = getPsiTypeParameterByName(psiOwner, name); 167 TypeParameterDescriptorInitialization typeParameterDescriptorInitialization = new TypeParameterDescriptorInitialization(typeParameterDescriptor, psiTypeParameter, upperBounds); 168 done(typeParameterDescriptorInitialization); 169 } 170 171 protected abstract void done(@NotNull TypeParameterDescriptorInitialization typeParameterDescriptor); 172 } 173 174 private class JetSignatureTypeParametersVisitor extends JetSignatureExceptionsAdapter { 175 @NotNull 176 private final DeclarationDescriptor containingDeclaration; 177 @NotNull 178 private final PsiTypeParameterListOwner psiOwner; 179 180 private final List<TypeParameterDescriptor> previousTypeParameters = new ArrayList<TypeParameterDescriptor>(); 181 // note changes state in this method 182 private final TypeVariableResolver typeVariableResolver; 183 184 185 private JetSignatureTypeParametersVisitor(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameterListOwner psiOwner, @NotNull String context) { 186 this.containingDeclaration = containingDeclaration; 187 this.psiOwner = psiOwner; 188 189 this.typeVariableResolver = TypeVariableResolvers.typeVariableResolverFromTypeParameters( 190 previousTypeParameters, 191 containingDeclaration, 192 context); 193 } 194 195 private int formalTypeParameterIndex = 0; 196 197 198 List<TypeParameterDescriptorInitialization> r = new ArrayList<TypeParameterDescriptorInitialization>(); 199 200 @Override 201 public JetSignatureVisitor visitFormalTypeParameter(final String name, TypeInfoVariance variance, boolean reified) { 202 TypeParameterDescriptorImpl typeParameter = TypeParameterDescriptorImpl.createForFurtherModification( 203 containingDeclaration, 204 Collections.<AnnotationDescriptor>emptyList(), // TODO: wrong 205 reified, 206 JetSignatureUtils.translateVariance(variance), 207 Name.identifier(name), 208 formalTypeParameterIndex++); 209 210 previousTypeParameters.add(typeParameter); 211 212 return new JetSignatureTypeParameterVisitor(psiOwner, name, typeVariableResolver, typeParameter) { 213 @Override 214 protected void done(@NotNull TypeParameterDescriptorInitialization typeParameterDescriptor) { 215 r.add(typeParameterDescriptor); 216 previousTypeParameters.add(typeParameterDescriptor.descriptor); 217 } 218 }; 219 } 220 } 221 222 /** 223 * @see #resolveMethodTypeParametersFromJetSignature(String, PsiMethod, DeclarationDescriptor) 224 */ 225 private List<TypeParameterDescriptorInitialization> resolveClassTypeParametersFromJetSignature(String jetSignature, 226 final PsiClass clazz, final ClassDescriptor classDescriptor) { 227 String context = "class " + clazz.getQualifiedName(); 228 JetSignatureTypeParametersVisitor jetSignatureTypeParametersVisitor = new JetSignatureTypeParametersVisitor(classDescriptor, clazz, context) { 229 @Override 230 public JetSignatureVisitor visitSuperclass() { 231 // TODO 232 return new JetSignatureAdapter(); 233 } 234 235 @Override 236 public JetSignatureVisitor visitInterface() { 237 // TODO 238 return new JetSignatureAdapter(); 239 } 240 }; 241 new JetSignatureReader(jetSignature).accept(jetSignatureTypeParametersVisitor); 242 return jetSignatureTypeParametersVisitor.r; 243 } 244 245 246 private static List<TypeParameterDescriptorInitialization> makeUninitializedTypeParameters( 247 @NotNull DeclarationDescriptor containingDeclaration, 248 @NotNull PsiTypeParameter[] typeParameters 249 ) { 250 List<TypeParameterDescriptorInitialization> result = Lists.newArrayList(); 251 for (PsiTypeParameter typeParameter : typeParameters) { 252 TypeParameterDescriptorInitialization typeParameterDescriptor = makeUninitializedTypeParameter(containingDeclaration, typeParameter); 253 result.add(typeParameterDescriptor); 254 } 255 return result; 256 } 257 258 @NotNull 259 private static TypeParameterDescriptorInitialization makeUninitializedTypeParameter( 260 @NotNull DeclarationDescriptor containingDeclaration, 261 @NotNull PsiTypeParameter psiTypeParameter 262 ) { 263 TypeParameterDescriptorImpl typeParameterDescriptor = TypeParameterDescriptorImpl.createForFurtherModification( 264 containingDeclaration, 265 Collections.<AnnotationDescriptor>emptyList(), // TODO 266 false, 267 Variance.INVARIANT, 268 Name.identifier(psiTypeParameter.getName()), 269 psiTypeParameter.getIndex() 270 ); 271 return new TypeParameterDescriptorInitialization(typeParameterDescriptor, psiTypeParameter); 272 } 273 274 private void initializeTypeParameter(TypeParameterDescriptorInitialization typeParameter, TypeVariableResolver typeVariableByPsiResolver) { 275 TypeParameterDescriptorImpl typeParameterDescriptor = typeParameter.descriptor; 276 if (typeParameter.origin == TypeParameterDescriptorOrigin.KOTLIN) { 277 List<JetType> upperBoundsForKotlin = typeParameter.upperBoundsForKotlin; 278 assert upperBoundsForKotlin != null; 279 if (upperBoundsForKotlin.size() == 0){ 280 typeParameterDescriptor.addUpperBound(KotlinBuiltIns.getInstance().getNullableAnyType()); 281 } 282 else { 283 for (JetType upperBound : upperBoundsForKotlin) { 284 typeParameterDescriptor.addUpperBound(upperBound); 285 } 286 } 287 288 // TODO: lower bounds 289 } 290 else { 291 PsiClassType[] referencedTypes = typeParameter.psiTypeParameter.getExtendsList().getReferencedTypes(); 292 if (referencedTypes.length == 0){ 293 typeParameterDescriptor.addUpperBound(KotlinBuiltIns.getInstance().getNullableAnyType()); 294 } 295 else if (referencedTypes.length == 1) { 296 typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedTypes[0], TypeUsage.UPPER_BOUND, typeVariableByPsiResolver)); 297 } 298 else { 299 for (PsiClassType referencedType : referencedTypes) { 300 typeParameterDescriptor.addUpperBound(semanticServices.getTypeTransformer().transformToType(referencedType, TypeUsage.UPPER_BOUND, typeVariableByPsiResolver)); 301 } 302 } 303 } 304 typeParameterDescriptor.setInitialized(); 305 } 306 307 public void initializeTypeParameters( 308 List<TypeParameterDescriptorInitialization> typeParametersInitialization, 309 @NotNull DeclarationDescriptor typeParametersOwner, 310 @NotNull String context 311 ) { 312 List<TypeParameterDescriptor> prevTypeParameters = Lists.newArrayList(); 313 314 List<TypeParameterDescriptor> typeParameters = Lists.newArrayList(); 315 for (TypeParameterDescriptorInitialization typeParameterDescriptor : typeParametersInitialization) { 316 typeParameters.add(typeParameterDescriptor.descriptor); 317 } 318 319 for (TypeParameterDescriptorInitialization psiTypeParameter : typeParametersInitialization) { 320 prevTypeParameters.add(psiTypeParameter.descriptor); 321 initializeTypeParameter(psiTypeParameter, 322 TypeVariableResolvers.typeVariableResolverFromTypeParameters(typeParameters, typeParametersOwner, context)); 323 } 324 } 325 326 327 public List<TypeParameterDescriptorInitialization> createUninitializedClassTypeParameters( 328 PsiClass psiClass, ClassDescriptor classDescriptor 329 ) { 330 JetClassAnnotation jetClassAnnotation = JetClassAnnotation.get(psiClass); 331 332 if (jetClassAnnotation.signature().length() > 0) { 333 return resolveClassTypeParametersFromJetSignature( 334 jetClassAnnotation.signature(), psiClass, classDescriptor); 335 } 336 337 return makeUninitializedTypeParameters(classDescriptor, psiClass.getTypeParameters()); 338 } 339 340 341 public List<TypeParameterDescriptor> resolveMethodTypeParameters( 342 @NotNull PsiMethodWrapper method, 343 @NotNull DeclarationDescriptor functionDescriptor 344 ) { 345 346 List<TypeParameterDescriptorInitialization> typeParametersIntialization; 347 PsiMethod psiMethod = method.getPsiMethod(); 348 if (method.getJetMethodAnnotation().typeParameters().length() > 0) { 349 typeParametersIntialization = resolveMethodTypeParametersFromJetSignature( 350 method.getJetMethodAnnotation().typeParameters(), psiMethod, functionDescriptor); 351 } 352 else { 353 typeParametersIntialization = makeUninitializedTypeParameters(functionDescriptor, psiMethod.getTypeParameters()); 354 } 355 356 PsiClass psiMethodContainingClass = psiMethod.getContainingClass(); 357 assert psiMethodContainingClass != null; 358 String context = "method " + method.getName() + " in class " + psiMethodContainingClass.getQualifiedName(); 359 initializeTypeParameters(typeParametersIntialization, functionDescriptor, context); 360 361 List<TypeParameterDescriptor> typeParameters = Lists.newArrayListWithCapacity(typeParametersIntialization.size()); 362 363 for (TypeParameterDescriptorInitialization tpdi : typeParametersIntialization) { 364 typeParameters.add(tpdi.descriptor); 365 } 366 367 return typeParameters; 368 } 369 370 /** 371 * @see #resolveClassTypeParametersFromJetSignature(String, PsiClass, ClassDescriptor) 372 */ 373 private List<TypeParameterDescriptorInitialization> resolveMethodTypeParametersFromJetSignature(String jetSignature, 374 PsiMethod method, DeclarationDescriptor functionDescriptor) 375 { 376 PsiClass methodContainingClass = method.getContainingClass(); 377 assert methodContainingClass != null; 378 String context = "method " + method.getName() + " in class " + methodContainingClass.getQualifiedName(); 379 JetSignatureTypeParametersVisitor jetSignatureTypeParametersVisitor = new JetSignatureTypeParametersVisitor(functionDescriptor, method, context); 380 new JetSignatureReader(jetSignature).acceptFormalTypeParametersOnly(jetSignatureTypeParametersVisitor); 381 return jetSignatureTypeParametersVisitor.r; 382 } 383 384}