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;
018
019 import jet.Function0;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.lang.descriptors.*;
023 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
024 import org.jetbrains.jet.lang.psi.*;
025 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
026 import org.jetbrains.jet.lang.resolve.scopes.LazyScopeAdapter;
027 import org.jetbrains.jet.lang.types.*;
028 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
029
030 import javax.inject.Inject;
031 import java.util.ArrayList;
032 import java.util.Collection;
033 import java.util.Collections;
034 import java.util.List;
035
036 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
037 import static org.jetbrains.jet.lang.resolve.PossiblyBareType.type;
038 import static org.jetbrains.jet.lang.types.Variance.*;
039 import static org.jetbrains.jet.storage.LockBasedStorageManager.NO_LOCKS;
040
041 public class TypeResolver {
042
043 private AnnotationResolver annotationResolver;
044 private QualifiedExpressionResolver qualifiedExpressionResolver;
045 private ModuleDescriptor moduleDescriptor;
046
047 @Inject
048 public void setAnnotationResolver(AnnotationResolver annotationResolver) {
049 this.annotationResolver = annotationResolver;
050 }
051
052 @Inject
053 public void setQualifiedExpressionResolver(QualifiedExpressionResolver qualifiedExpressionResolver) {
054 this.qualifiedExpressionResolver = qualifiedExpressionResolver;
055 }
056
057 @Inject
058 public void setModuleDescriptor(@NotNull ModuleDescriptor moduleDescriptor) {
059 this.moduleDescriptor = moduleDescriptor;
060 }
061
062 @NotNull
063 public JetType resolveType(@NotNull JetScope scope, @NotNull JetTypeReference typeReference, BindingTrace trace, boolean checkBounds) {
064 // bare types are not allowed
065 return resolveType(new TypeResolutionContext(scope, trace, checkBounds, false), typeReference);
066 }
067
068 @NotNull
069 public JetType resolveType(@NotNull TypeResolutionContext c, @NotNull JetTypeReference typeReference) {
070 assert !c.allowBareTypes : "Use resolvePossiblyBareType() when bare types are allowed";
071 return resolvePossiblyBareType(c, typeReference).getActualType();
072 }
073
074 @NotNull
075 public PossiblyBareType resolvePossiblyBareType(@NotNull TypeResolutionContext c, @NotNull JetTypeReference typeReference) {
076 JetType cachedType = c.trace.getBindingContext().get(BindingContext.TYPE, typeReference);
077 if (cachedType != null) return type(cachedType);
078
079 List<AnnotationDescriptor> annotations = annotationResolver.getResolvedAnnotations(typeReference.getAnnotations(), c.trace);
080
081 JetTypeElement typeElement = typeReference.getTypeElement();
082 PossiblyBareType type = resolveTypeElement(c, annotations, typeElement);
083 if (!type.isBare()) {
084 c.trace.record(BindingContext.TYPE, typeReference, type.getActualType());
085 }
086 c.trace.record(BindingContext.TYPE_RESOLUTION_SCOPE, typeReference, c.scope);
087
088 return type;
089 }
090
091 @NotNull
092 private PossiblyBareType resolveTypeElement(
093 final TypeResolutionContext c,
094 final List<AnnotationDescriptor> annotations,
095 JetTypeElement typeElement
096 ) {
097
098 final PossiblyBareType[] result = new PossiblyBareType[1];
099 if (typeElement != null) {
100 typeElement.accept(new JetVisitorVoid() {
101 @Override
102 public void visitUserType(@NotNull JetUserType type) {
103 JetSimpleNameExpression referenceExpression = type.getReferenceExpression();
104 String referencedName = type.getReferencedName();
105 if (referenceExpression == null || referencedName == null) {
106 return;
107 }
108
109 ClassifierDescriptor classifierDescriptor = resolveClass(c.scope, type, c.trace);
110 if (classifierDescriptor == null) {
111 resolveTypeProjections(c, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
112 return;
113 }
114
115 c.trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classifierDescriptor);
116
117 if (classifierDescriptor instanceof TypeParameterDescriptor) {
118 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) classifierDescriptor;
119
120 JetScope scopeForTypeParameter = getScopeForTypeParameter(c, typeParameterDescriptor);
121 if (scopeForTypeParameter instanceof ErrorUtils.ErrorScope) {
122 result[0] = type(ErrorUtils.createErrorType("?"));
123 }
124 else {
125 result[0] = type(new JetTypeImpl(
126 annotations,
127 typeParameterDescriptor.getTypeConstructor(),
128 TypeUtils.hasNullableLowerBound(typeParameterDescriptor),
129 Collections.<TypeProjection>emptyList(),
130 scopeForTypeParameter
131 ));
132 }
133
134 resolveTypeProjections(c, ErrorUtils.createErrorType("No type").getConstructor(), type.getTypeArguments());
135
136 DeclarationDescriptor containing = typeParameterDescriptor.getContainingDeclaration();
137 if (containing instanceof ClassDescriptor) {
138 // Type parameter can't be inherited from member of parent class, so we can skip subclass check
139 DescriptorResolver.checkHasOuterClassInstance(c.scope, c.trace, referenceExpression, (ClassDescriptor) containing, false);
140 }
141 }
142 else if (classifierDescriptor instanceof ClassDescriptor) {
143 ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor;
144
145 TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
146 List<TypeProjection> arguments = resolveTypeProjections(c, typeConstructor, type.getTypeArguments());
147 List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
148 int expectedArgumentCount = parameters.size();
149 int actualArgumentCount = arguments.size();
150 if (ErrorUtils.isError(classDescriptor)) {
151 result[0] = type(ErrorUtils.createErrorType("[Error type: " + typeConstructor + "]"));
152 }
153 else {
154 if (actualArgumentCount != expectedArgumentCount) {
155 if (actualArgumentCount == 0) {
156 // See docs for PossiblyBareType
157 if (c.allowBareTypes) {
158 result[0] = PossiblyBareType.bare(typeConstructor, false);
159 return;
160 }
161 c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type, expectedArgumentCount));
162 }
163 else {
164 c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type.getTypeArgumentList(), expectedArgumentCount));
165 }
166 }
167 else {
168 JetTypeImpl resultingType = new JetTypeImpl(
169 annotations,
170 typeConstructor,
171 false,
172 arguments,
173 classDescriptor.getMemberScope(arguments)
174 );
175 result[0] = type(resultingType);
176 if (c.checkBounds) {
177 TypeSubstitutor substitutor = TypeSubstitutor.create(resultingType);
178 for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
179 TypeParameterDescriptor parameter = parameters.get(i);
180 JetType argument = arguments.get(i).getType();
181 JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
182
183 if (typeReference != null) {
184 DescriptorResolver.checkBounds(typeReference, argument, parameter, substitutor, c.trace);
185 }
186 }
187 }
188 }
189 }
190 }
191 }
192
193 @Override
194 public void visitNullableType(@NotNull JetNullableType nullableType) {
195 PossiblyBareType baseType = resolveTypeElement(c, annotations, nullableType.getInnerType());
196 if (baseType.isNullable()) {
197 c.trace.report(REDUNDANT_NULLABLE.on(nullableType));
198 }
199 else if (!baseType.isBare() && TypeUtils.hasNullableSuperType(baseType.getActualType())) {
200 c.trace.report(BASE_WITH_NULLABLE_UPPER_BOUND.on(nullableType, baseType.getActualType()));
201 }
202 result[0] = baseType.makeNullable();
203 }
204
205 @Override
206 public void visitFunctionType(@NotNull JetFunctionType type) {
207 JetTypeReference receiverTypeRef = type.getReceiverTypeRef();
208 JetType receiverType = receiverTypeRef == null ? null : resolveType(c.noBareTypes(), receiverTypeRef);
209
210 List<JetType> parameterTypes = new ArrayList<JetType>();
211 for (JetParameter parameter : type.getParameters()) {
212 parameterTypes.add(resolveType(c.noBareTypes(), parameter.getTypeReference()));
213 }
214
215 JetTypeReference returnTypeRef = type.getReturnTypeRef();
216 JetType returnType;
217 if (returnTypeRef != null) {
218 returnType = resolveType(c.noBareTypes(), returnTypeRef);
219 }
220 else {
221 returnType = KotlinBuiltIns.getInstance().getUnitType();
222 }
223 result[0] = type(KotlinBuiltIns.getInstance().getFunctionType(annotations, receiverType, parameterTypes, returnType));
224 }
225
226 @Override
227 public void visitJetElement(@NotNull JetElement element) {
228 c.trace.report(UNSUPPORTED.on(element, "Self-types are not supported yet"));
229 }
230 });
231 }
232 if (result[0] == null) {
233 return type(ErrorUtils.createErrorType(typeElement == null ? "No type element" : typeElement.getText()));
234 }
235 return result[0];
236 }
237
238 private JetScope getScopeForTypeParameter(TypeResolutionContext c, final TypeParameterDescriptor typeParameterDescriptor) {
239 if (c.checkBounds) {
240 return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope();
241 }
242 else {
243 return new LazyScopeAdapter(NO_LOCKS.createLazyValue(new Function0<JetScope>() {
244 @Override
245 public JetScope invoke() {
246 return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope();
247 }
248 }));
249 }
250 }
251
252 @NotNull
253 private List<TypeProjection> resolveTypeProjections(
254 TypeResolutionContext c,
255 TypeConstructor constructor,
256 List<JetTypeProjection> argumentElements
257 ) {
258 List<TypeProjection> arguments = new ArrayList<TypeProjection>();
259 for (int i = 0, argumentElementsSize = argumentElements.size(); i < argumentElementsSize; i++) {
260 JetTypeProjection argumentElement = argumentElements.get(i);
261
262 JetProjectionKind projectionKind = argumentElement.getProjectionKind();
263 JetType type;
264 if (projectionKind == JetProjectionKind.STAR) {
265 List<TypeParameterDescriptor> parameters = constructor.getParameters();
266 if (parameters.size() > i) {
267 TypeParameterDescriptor parameterDescriptor = parameters.get(i);
268 arguments.add(SubstitutionUtils.makeStarProjection(parameterDescriptor));
269 }
270 else {
271 arguments.add(new TypeProjectionImpl(OUT_VARIANCE, ErrorUtils.createErrorType("*")));
272 }
273 }
274 else {
275 // TODO : handle the Foo<in *> case
276 type = resolveType(c.noBareTypes(), argumentElement.getTypeReference());
277 Variance kind = resolveProjectionKind(projectionKind);
278 if (constructor.getParameters().size() > i) {
279 TypeParameterDescriptor parameterDescriptor = constructor.getParameters().get(i);
280 if (kind != INVARIANT && parameterDescriptor.getVariance() != INVARIANT) {
281 if (kind == parameterDescriptor.getVariance()) {
282 c.trace.report(REDUNDANT_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
283 }
284 else {
285 c.trace.report(CONFLICTING_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
286 }
287 }
288 }
289 arguments.add(new TypeProjectionImpl(kind, type));
290 }
291 }
292 return arguments;
293 }
294
295 @NotNull
296 public static Variance resolveProjectionKind(@NotNull JetProjectionKind projectionKind) {
297 Variance kind = null;
298 switch (projectionKind) {
299 case IN:
300 kind = IN_VARIANCE;
301 break;
302 case OUT:
303 kind = OUT_VARIANCE;
304 break;
305 case NONE:
306 kind = INVARIANT;
307 break;
308 default:
309 // NOTE: Star projections must be handled before this method is called
310 throw new IllegalStateException("Illegal projection kind:" + projectionKind);
311 }
312 return kind;
313 }
314
315 @Nullable
316 public ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType, BindingTrace trace) {
317 Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver.lookupDescriptorsForUserType(userType, scope, trace);
318 for (DeclarationDescriptor descriptor : descriptors) {
319 if (descriptor instanceof ClassifierDescriptor) {
320 ImportsResolver.reportPlatformClassMappedToKotlin(moduleDescriptor, trace, userType, descriptor);
321 return (ClassifierDescriptor) descriptor;
322 }
323 }
324 return null;
325 }
326 }