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