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.intellij.psi.*;
021 import jet.typeinfo.TypeInfoVariance;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.jet.lang.descriptors.*;
025 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
026 import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
027 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
028 import org.jetbrains.jet.lang.resolve.java.*;
029 import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation;
030 import org.jetbrains.jet.lang.resolve.java.wrapper.PsiMethodWrapper;
031 import org.jetbrains.jet.lang.resolve.name.Name;
032 import org.jetbrains.jet.lang.types.JetType;
033 import org.jetbrains.jet.lang.types.Variance;
034 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
035 import org.jetbrains.jet.rt.signature.JetSignatureAdapter;
036 import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter;
037 import org.jetbrains.jet.rt.signature.JetSignatureReader;
038 import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
039
040 import javax.inject.Inject;
041 import java.util.ArrayList;
042 import java.util.Collections;
043 import java.util.List;
044
045 public 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 }