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 kotlin.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.Annotations;
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 Annotations 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 Annotations 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 DescriptorResolver.checkHasOuterClassInstance(c.scope, c.trace, referenceExpression, (ClassDescriptor) containing);
139 }
140 }
141 else if (classifierDescriptor instanceof ClassDescriptor) {
142 ClassDescriptor classDescriptor = (ClassDescriptor) classifierDescriptor;
143
144 TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
145 List<TypeProjection> arguments = resolveTypeProjections(c, typeConstructor, type.getTypeArguments());
146 List<TypeParameterDescriptor> parameters = typeConstructor.getParameters();
147 int expectedArgumentCount = parameters.size();
148 int actualArgumentCount = arguments.size();
149 if (ErrorUtils.isError(classDescriptor)) {
150 result[0] = type(ErrorUtils.createErrorType("[Error type: " + typeConstructor + "]"));
151 }
152 else {
153 if (actualArgumentCount != expectedArgumentCount) {
154 if (actualArgumentCount == 0) {
155 // See docs for PossiblyBareType
156 if (c.allowBareTypes) {
157 result[0] = PossiblyBareType.bare(typeConstructor, false);
158 return;
159 }
160 c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type, expectedArgumentCount));
161 }
162 else {
163 c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(type.getTypeArgumentList(), expectedArgumentCount));
164 }
165 }
166 else {
167 JetTypeImpl resultingType = new JetTypeImpl(
168 annotations,
169 typeConstructor,
170 false,
171 arguments,
172 classDescriptor.getMemberScope(arguments)
173 );
174 result[0] = type(resultingType);
175 if (c.checkBounds) {
176 TypeSubstitutor substitutor = TypeSubstitutor.create(resultingType);
177 for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
178 TypeParameterDescriptor parameter = parameters.get(i);
179 JetType argument = arguments.get(i).getType();
180 JetTypeReference typeReference = type.getTypeArguments().get(i).getTypeReference();
181
182 if (typeReference != null) {
183 DescriptorResolver.checkBounds(typeReference, argument, parameter, substitutor, c.trace);
184 }
185 }
186 }
187 }
188 }
189 }
190 }
191
192 @Override
193 public void visitNullableType(@NotNull JetNullableType nullableType) {
194 PossiblyBareType baseType = resolveTypeElement(c, annotations, nullableType.getInnerType());
195 if (baseType.isNullable()) {
196 c.trace.report(REDUNDANT_NULLABLE.on(nullableType));
197 }
198 else if (!baseType.isBare() && TypeUtils.hasNullableSuperType(baseType.getActualType())) {
199 c.trace.report(BASE_WITH_NULLABLE_UPPER_BOUND.on(nullableType, baseType.getActualType()));
200 }
201 result[0] = baseType.makeNullable();
202 }
203
204 @Override
205 public void visitFunctionType(@NotNull JetFunctionType type) {
206 JetTypeReference receiverTypeRef = type.getReceiverTypeRef();
207 JetType receiverType = receiverTypeRef == null ? null : resolveType(c.noBareTypes(), receiverTypeRef);
208
209 List<JetType> parameterTypes = new ArrayList<JetType>();
210 for (JetParameter parameter : type.getParameters()) {
211 parameterTypes.add(resolveType(c.noBareTypes(), parameter.getTypeReference()));
212 }
213
214 JetTypeReference returnTypeRef = type.getReturnTypeRef();
215 JetType returnType;
216 if (returnTypeRef != null) {
217 returnType = resolveType(c.noBareTypes(), returnTypeRef);
218 }
219 else {
220 returnType = KotlinBuiltIns.getInstance().getUnitType();
221 }
222 result[0] = type(KotlinBuiltIns.getInstance().getFunctionType(annotations, receiverType, parameterTypes, returnType));
223 }
224
225 @Override
226 public void visitJetElement(@NotNull JetElement element) {
227 c.trace.report(UNSUPPORTED.on(element, "Self-types are not supported yet"));
228 }
229 });
230 }
231 if (result[0] == null) {
232 return type(ErrorUtils.createErrorType(typeElement == null ? "No type element" : typeElement.getText()));
233 }
234 return result[0];
235 }
236
237 private JetScope getScopeForTypeParameter(TypeResolutionContext c, final TypeParameterDescriptor typeParameterDescriptor) {
238 if (c.checkBounds) {
239 return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope();
240 }
241 else {
242 return new LazyScopeAdapter(NO_LOCKS.createLazyValue(new Function0<JetScope>() {
243 @Override
244 public JetScope invoke() {
245 return typeParameterDescriptor.getUpperBoundsAsType().getMemberScope();
246 }
247 }));
248 }
249 }
250
251 @NotNull
252 private List<TypeProjection> resolveTypeProjections(
253 TypeResolutionContext c,
254 TypeConstructor constructor,
255 List<JetTypeProjection> argumentElements
256 ) {
257 List<TypeProjection> arguments = new ArrayList<TypeProjection>();
258 for (int i = 0, argumentElementsSize = argumentElements.size(); i < argumentElementsSize; i++) {
259 JetTypeProjection argumentElement = argumentElements.get(i);
260
261 JetProjectionKind projectionKind = argumentElement.getProjectionKind();
262 JetType type;
263 if (projectionKind == JetProjectionKind.STAR) {
264 List<TypeParameterDescriptor> parameters = constructor.getParameters();
265 if (parameters.size() > i) {
266 TypeParameterDescriptor parameterDescriptor = parameters.get(i);
267 arguments.add(TypeUtils.makeStarProjection(parameterDescriptor));
268 }
269 else {
270 arguments.add(new TypeProjectionImpl(OUT_VARIANCE, ErrorUtils.createErrorType("*")));
271 }
272 }
273 else {
274 // TODO : handle the Foo<in *> case
275 type = resolveType(c.noBareTypes(), argumentElement.getTypeReference());
276 Variance kind = resolveProjectionKind(projectionKind);
277 if (constructor.getParameters().size() > i) {
278 TypeParameterDescriptor parameterDescriptor = constructor.getParameters().get(i);
279 if (kind != INVARIANT && parameterDescriptor.getVariance() != INVARIANT) {
280 if (kind == parameterDescriptor.getVariance()) {
281 c.trace.report(REDUNDANT_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
282 }
283 else {
284 c.trace.report(CONFLICTING_PROJECTION.on(argumentElement, constructor.getDeclarationDescriptor()));
285 }
286 }
287 }
288 arguments.add(new TypeProjectionImpl(kind, type));
289 }
290 }
291 return arguments;
292 }
293
294 @NotNull
295 public static Variance resolveProjectionKind(@NotNull JetProjectionKind projectionKind) {
296 Variance kind = null;
297 switch (projectionKind) {
298 case IN:
299 kind = IN_VARIANCE;
300 break;
301 case OUT:
302 kind = OUT_VARIANCE;
303 break;
304 case NONE:
305 kind = INVARIANT;
306 break;
307 default:
308 // NOTE: Star projections must be handled before this method is called
309 throw new IllegalStateException("Illegal projection kind:" + projectionKind);
310 }
311 return kind;
312 }
313
314 @Nullable
315 public ClassifierDescriptor resolveClass(JetScope scope, JetUserType userType, BindingTrace trace) {
316 Collection<? extends DeclarationDescriptor> descriptors = qualifiedExpressionResolver.lookupDescriptorsForUserType(userType, scope, trace);
317 for (DeclarationDescriptor descriptor : descriptors) {
318 if (descriptor instanceof ClassifierDescriptor) {
319 ImportsResolver.reportPlatformClassMappedToKotlin(moduleDescriptor, trace, userType, descriptor);
320 return (ClassifierDescriptor) descriptor;
321 }
322 }
323 return null;
324 }
325 }