001 /*
002 * Copyright 2010-2015 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.kotlin.resolve;
018
019 import com.google.common.collect.ImmutableSet;
020 import com.google.common.collect.Multimap;
021 import com.google.common.collect.Sets;
022 import com.intellij.psi.PsiElement;
023 import kotlin.jvm.functions.Function1;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
027 import org.jetbrains.kotlin.descriptors.*;
028 import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0;
029 import org.jetbrains.kotlin.diagnostics.Errors;
030 import org.jetbrains.kotlin.lexer.KtModifierKeywordToken;
031 import org.jetbrains.kotlin.lexer.KtTokens;
032 import org.jetbrains.kotlin.psi.*;
033 import org.jetbrains.kotlin.types.*;
034 import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
035 import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
036
037 import java.util.*;
038
039 import static org.jetbrains.kotlin.diagnostics.Errors.*;
040 import static org.jetbrains.kotlin.resolve.BindingContext.TYPE;
041 import static org.jetbrains.kotlin.resolve.BindingContext.TYPE_PARAMETER;
042 import static org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers;
043 import static org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembers;
044
045 public class DeclarationsChecker {
046 @NotNull private final BindingTrace trace;
047 @NotNull private final ModifiersChecker.ModifiersCheckingProcedure modifiersChecker;
048 @NotNull private final DescriptorResolver descriptorResolver;
049 @NotNull private final AnnotationChecker annotationChecker;
050 @NotNull private final IdentifierChecker identifierChecker;
051
052 public DeclarationsChecker(
053 @NotNull DescriptorResolver descriptorResolver,
054 @NotNull ModifiersChecker modifiersChecker,
055 @NotNull AnnotationChecker annotationChecker,
056 @NotNull IdentifierChecker identifierChecker,
057 @NotNull BindingTrace trace
058 ) {
059 this.descriptorResolver = descriptorResolver;
060 this.modifiersChecker = modifiersChecker.withTrace(trace);
061 this.annotationChecker = annotationChecker;
062 this.identifierChecker = identifierChecker;
063 this.trace = trace;
064 }
065
066 public void process(@NotNull BodiesResolveContext bodiesResolveContext) {
067 for (KtFile file : bodiesResolveContext.getFiles()) {
068 checkModifiersAndAnnotationsInPackageDirective(file);
069 annotationChecker.check(file, trace, null);
070 }
071
072 Map<KtClassOrObject, ClassDescriptorWithResolutionScopes> classes = bodiesResolveContext.getDeclaredClasses();
073 for (Map.Entry<KtClassOrObject, ClassDescriptorWithResolutionScopes> entry : classes.entrySet()) {
074 KtClassOrObject classOrObject = entry.getKey();
075 ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
076
077 checkSupertypesForConsistency(classOrObject, classDescriptor);
078 checkTypesInClassHeader(classOrObject);
079
080 if (classOrObject instanceof KtClass) {
081 KtClass ktClass = (KtClass) classOrObject;
082 checkClass(bodiesResolveContext, ktClass, classDescriptor);
083 descriptorResolver.checkNamesInConstraints(
084 ktClass, classDescriptor, classDescriptor.getScopeForClassHeaderResolution(), trace);
085 }
086 else if (classOrObject instanceof KtObjectDeclaration) {
087 checkObject((KtObjectDeclaration) classOrObject, classDescriptor);
088 }
089
090 checkPrimaryConstructor(classOrObject, classDescriptor);
091
092 modifiersChecker.checkModifiersForDeclaration(classOrObject, classDescriptor);
093 identifierChecker.checkDeclaration(classOrObject, trace);
094 checkClassExposedType(classOrObject, classDescriptor);
095 }
096
097 Map<KtNamedFunction, SimpleFunctionDescriptor> functions = bodiesResolveContext.getFunctions();
098 for (Map.Entry<KtNamedFunction, SimpleFunctionDescriptor> entry : functions.entrySet()) {
099 KtNamedFunction function = entry.getKey();
100 SimpleFunctionDescriptor functionDescriptor = entry.getValue();
101
102 checkFunction(function, functionDescriptor);
103 modifiersChecker.checkModifiersForDeclaration(function, functionDescriptor);
104 identifierChecker.checkDeclaration(function, trace);
105 }
106
107 Map<KtProperty, PropertyDescriptor> properties = bodiesResolveContext.getProperties();
108 for (Map.Entry<KtProperty, PropertyDescriptor> entry : properties.entrySet()) {
109 KtProperty property = entry.getKey();
110 PropertyDescriptor propertyDescriptor = entry.getValue();
111
112 checkProperty(property, propertyDescriptor);
113 modifiersChecker.checkModifiersForDeclaration(property, propertyDescriptor);
114 identifierChecker.checkDeclaration(property, trace);
115 }
116
117 for (Map.Entry<KtSecondaryConstructor, ConstructorDescriptor> entry : bodiesResolveContext.getSecondaryConstructors().entrySet()) {
118 ConstructorDescriptor constructorDescriptor = entry.getValue();
119 KtSecondaryConstructor declaration = entry.getKey();
120 checkConstructorDeclaration(constructorDescriptor, declaration);
121 checkFunctionExposedType(declaration, constructorDescriptor);
122 }
123 }
124
125 private void checkConstructorDeclaration(ConstructorDescriptor constructorDescriptor, KtDeclaration declaration) {
126 modifiersChecker.checkModifiersForDeclaration(declaration, constructorDescriptor);
127 identifierChecker.checkDeclaration(declaration, trace);
128 }
129
130 private void checkModifiersAndAnnotationsInPackageDirective(KtFile file) {
131 KtPackageDirective packageDirective = file.getPackageDirective();
132 if (packageDirective == null) return;
133
134 KtModifierList modifierList = packageDirective.getModifierList();
135 if (modifierList == null) return;
136
137 for (KtAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) {
138 KtConstructorCalleeExpression calleeExpression = annotationEntry.getCalleeExpression();
139 if (calleeExpression != null) {
140 KtReferenceExpression reference = calleeExpression.getConstructorReferenceExpression();
141 if (reference != null) {
142 trace.report(UNRESOLVED_REFERENCE.on(reference, reference));
143 }
144 }
145 }
146 annotationChecker.check(packageDirective, trace, null);
147 ModifierCheckerCore.INSTANCE$.check(packageDirective, trace, null);
148 }
149
150 private void checkTypesInClassHeader(@NotNull KtClassOrObject classOrObject) {
151 for (KtDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) {
152 checkBoundsForTypeInClassHeader(delegationSpecifier.getTypeReference());
153 }
154
155 if (!(classOrObject instanceof KtClass)) return;
156 KtClass ktClass = (KtClass) classOrObject;
157
158 for (KtTypeParameter jetTypeParameter : ktClass.getTypeParameters()) {
159 checkBoundsForTypeInClassHeader(jetTypeParameter.getExtendsBound());
160 checkFinalUpperBounds(jetTypeParameter.getExtendsBound());
161 }
162
163 for (KtTypeConstraint constraint : ktClass.getTypeConstraints()) {
164 checkBoundsForTypeInClassHeader(constraint.getBoundTypeReference());
165 checkFinalUpperBounds(constraint.getBoundTypeReference());
166 }
167 }
168
169 private void checkBoundsForTypeInClassHeader(@Nullable KtTypeReference typeReference) {
170 if (typeReference != null) {
171 KotlinType type = trace.getBindingContext().get(TYPE, typeReference);
172 if (type != null) {
173 DescriptorResolver.checkBounds(typeReference, type, trace);
174 }
175 }
176 }
177
178 private void checkFinalUpperBounds(@Nullable KtTypeReference typeReference) {
179 if (typeReference != null) {
180 KotlinType type = trace.getBindingContext().get(TYPE, typeReference);
181 if (type != null) {
182 DescriptorResolver.checkUpperBoundType(typeReference, type, trace);
183 }
184 }
185 }
186
187 private void checkSupertypesForConsistency(
188 @NotNull KtClassOrObject classOrObject,
189 @NotNull ClassDescriptor classDescriptor
190 ) {
191 checkSupertypesForConsistency(classDescriptor, classOrObject);
192 }
193
194 private void checkSupertypesForConsistency(
195 @NotNull KtTypeParameter typeParameter,
196 @NotNull TypeParameterDescriptor typeParameterDescriptor
197 ) {
198 checkSupertypesForConsistency(typeParameterDescriptor, typeParameter);
199 }
200
201 private void checkSupertypesForConsistency(
202 @NotNull ClassifierDescriptor classifierDescriptor,
203 @NotNull PsiElement sourceElement
204 ) {
205 Multimap<TypeConstructor, TypeProjection> multimap =
206 SubstitutionUtils.buildDeepSubstitutionMultimap(classifierDescriptor.getDefaultType());
207 for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) {
208 Collection<TypeProjection> projections = entry.getValue();
209 if (projections.size() > 1) {
210 TypeConstructor typeConstructor = entry.getKey();
211 DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor();
212 assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor;
213 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor;
214
215 // Immediate arguments of supertypes cannot be projected
216 Set<KotlinType> conflictingTypes = Sets.newLinkedHashSet();
217 for (TypeProjection projection : projections) {
218 conflictingTypes.add(projection.getType());
219 }
220 removeDuplicateTypes(conflictingTypes);
221 if (conflictingTypes.size() > 1) {
222 DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
223 assert containingDeclaration instanceof ClassDescriptor : containingDeclaration;
224 if (sourceElement instanceof KtClassOrObject) {
225 KtDelegationSpecifierList delegationSpecifierList = ((KtClassOrObject) sourceElement).getDelegationSpecifierList();
226 assert delegationSpecifierList != null;
227 // trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + " has inconsistent values: " + conflictingTypes);
228 trace.report(INCONSISTENT_TYPE_PARAMETER_VALUES
229 .on(delegationSpecifierList, typeParameterDescriptor, (ClassDescriptor) containingDeclaration,
230 conflictingTypes));
231 }
232 else if (sourceElement instanceof KtTypeParameter) {
233 trace.report(INCONSISTENT_TYPE_PARAMETER_BOUNDS
234 .on((KtTypeParameter) sourceElement, typeParameterDescriptor, (ClassDescriptor) containingDeclaration,
235 conflictingTypes));
236 }
237 }
238 }
239 }
240 }
241
242 private void checkClassExposedType(@NotNull KtClassOrObject klass, @NotNull ClassDescriptor classDescriptor) {
243 checkExposedSupertypes(klass, classDescriptor);
244 checkExposedParameterBounds(klass, classDescriptor);
245
246 if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null && klass.getPrimaryConstructor() != null) {
247 checkFunctionExposedType(klass.getPrimaryConstructor(), classDescriptor.getUnsubstitutedPrimaryConstructor());
248 }
249 }
250
251 private void checkExposedParameterBounds(@NotNull KtClassOrObject klass, @NotNull ClassDescriptor classDescriptor) {
252 EffectiveVisibility classVisibility = EffectiveVisibility.Companion.forClass(classDescriptor);
253 List<KtTypeParameter> typeParameterList = klass.getTypeParameters();
254 int i = 0;
255 for (TypeParameterDescriptor typeParameterDescriptor : classDescriptor.getTypeConstructor().getParameters()) {
256 if (i >= typeParameterList.size()) return;
257 for (KotlinType upperBound : typeParameterDescriptor.getUpperBounds()) {
258 EffectiveVisibility upperBoundVisibility = EffectiveVisibility.Companion.forType(upperBound);
259 if (!upperBoundVisibility.sameOrMorePermissive(classVisibility)) {
260 KtTypeParameter typeParameter = typeParameterList.get(i);
261 trace.report(EXPOSED_TYPE_PARAMETER_BOUND.on(typeParameter, classVisibility, upperBoundVisibility));
262 break;
263 }
264 }
265 i++;
266 }
267 }
268
269 private void checkExposedSupertypes(@NotNull KtClassOrObject klass, @NotNull ClassDescriptor classDescriptor) {
270 EffectiveVisibility classVisibility = EffectiveVisibility.Companion.forClass(classDescriptor);
271 boolean isInterface = classDescriptor.getKind() == ClassKind.INTERFACE;
272 List<KtDelegationSpecifier> delegationList = klass.getDelegationSpecifiers();
273 int i = -1;
274 for (KotlinType superType : classDescriptor.getTypeConstructor().getSupertypes()) {
275 i++;
276 if (i >= delegationList.size()) return;
277 ClassDescriptor superDescriptor = TypeUtils.getClassDescriptor(superType);
278 if (superDescriptor == null) {
279 continue;
280 }
281 boolean superIsInterface = superDescriptor.getKind() == ClassKind.INTERFACE;
282 if (superIsInterface != isInterface) {
283 continue;
284 }
285 EffectiveVisibility superTypeVisibility = EffectiveVisibility.Companion.forType(superType);
286 if (!superTypeVisibility.sameOrMorePermissive(classVisibility)) {
287 if (isInterface) {
288 trace.report(EXPOSED_SUPER_INTERFACE.on(delegationList.get(i), classVisibility, superTypeVisibility));
289 }
290 else {
291 trace.report(EXPOSED_SUPER_CLASS.on(delegationList.get(i), classVisibility, superTypeVisibility));
292 }
293 }
294 }
295 }
296
297 private static void removeDuplicateTypes(Set<KotlinType> conflictingTypes) {
298 for (Iterator<KotlinType> iterator = conflictingTypes.iterator(); iterator.hasNext(); ) {
299 KotlinType type = iterator.next();
300 for (KotlinType otherType : conflictingTypes) {
301 boolean subtypeOf = KotlinTypeChecker.DEFAULT.equalTypes(type, otherType);
302 if (type != otherType && subtypeOf) {
303 iterator.remove();
304 break;
305 }
306 }
307 }
308 }
309
310 private void checkObject(KtObjectDeclaration declaration, ClassDescriptor classDescriptor) {
311 if (declaration.isLocal() && !declaration.isCompanion() && !declaration.isObjectLiteral()) {
312 trace.report(LOCAL_OBJECT_NOT_ALLOWED.on(declaration, classDescriptor));
313 }
314 }
315
316 private void checkClass(BodiesResolveContext c, KtClass aClass, ClassDescriptorWithResolutionScopes classDescriptor) {
317 checkOpenMembers(classDescriptor);
318 checkTypeParameters(aClass);
319 checkTypeParameterConstraints(aClass);
320 FiniteBoundRestrictionChecker.check(aClass, classDescriptor, trace);
321 NonExpansiveInheritanceRestrictionChecker.check(aClass, classDescriptor, trace);
322
323 if (aClass.isInterface()) {
324 checkConstructorInInterface(aClass);
325 checkMethodsOfAnyInInterface(classDescriptor);
326 if (aClass.isLocal() && !(classDescriptor.getContainingDeclaration() instanceof ClassDescriptor)) {
327 trace.report(LOCAL_INTERFACE_NOT_ALLOWED.on(aClass, classDescriptor));
328 }
329 }
330 else if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) {
331 checkAnnotationClassWithBody(aClass);
332 checkValOnAnnotationParameter(aClass);
333 }
334 else if (aClass instanceof KtEnumEntry) {
335 checkEnumEntry((KtEnumEntry) aClass, classDescriptor);
336 }
337 for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) {
338 if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) continue;
339 KtNamedDeclaration member = (KtNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor);
340 if (member instanceof KtFunction && memberDescriptor instanceof FunctionDescriptor) {
341 checkFunctionExposedType((KtFunction) member, (FunctionDescriptor) memberDescriptor);
342 }
343 }
344 }
345
346 private void checkPrimaryConstructor(KtClassOrObject classOrObject, ClassDescriptor classDescriptor) {
347 ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
348 KtPrimaryConstructor declaration = classOrObject.getPrimaryConstructor();
349 if (primaryConstructor == null || declaration == null) return;
350
351 for (KtParameter parameter : declaration.getValueParameters()) {
352 PropertyDescriptor propertyDescriptor = trace.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
353 if (propertyDescriptor != null) {
354 modifiersChecker.checkModifiersForDeclaration(parameter, propertyDescriptor);
355 checkPropertyLateInit(parameter, propertyDescriptor);
356 }
357 }
358
359 if (declaration.getModifierList() != null && !declaration.hasConstructorKeyword()) {
360 trace.report(MISSING_CONSTRUCTOR_KEYWORD.on(declaration.getModifierList()));
361 }
362
363 if (!(classOrObject instanceof KtClass)) {
364 trace.report(CONSTRUCTOR_IN_OBJECT.on(declaration));
365 }
366
367 checkConstructorDeclaration(primaryConstructor, declaration);
368 }
369
370 private void checkTypeParameters(KtTypeParameterListOwner typeParameterListOwner) {
371 // TODO: Support annotation for type parameters
372 for (KtTypeParameter jetTypeParameter : typeParameterListOwner.getTypeParameters()) {
373 AnnotationResolver.reportUnsupportedAnnotationForTypeParameter(jetTypeParameter, trace);
374
375 TypeParameterDescriptor typeParameter = trace.get(TYPE_PARAMETER, jetTypeParameter);
376 if (typeParameter != null) {
377 DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter);
378 }
379 }
380 }
381
382 private void checkTypeParameterConstraints(KtTypeParameterListOwner typeParameterListOwner) {
383 List<KtTypeConstraint> constraints = typeParameterListOwner.getTypeConstraints();
384 if (!constraints.isEmpty()) {
385 for (KtTypeParameter typeParameter : typeParameterListOwner.getTypeParameters()) {
386 if (typeParameter.getExtendsBound() != null && hasConstraints(typeParameter, constraints)) {
387 trace.report(MISPLACED_TYPE_PARAMETER_CONSTRAINTS.on(typeParameter));
388 }
389 TypeParameterDescriptor descriptor = trace.get(TYPE_PARAMETER, typeParameter);
390 if (descriptor != null) {
391 checkSupertypesForConsistency(typeParameter, descriptor);
392 }
393 }
394 }
395 }
396
397 private static boolean hasConstraints(KtTypeParameter typeParameter, List<KtTypeConstraint> constraints) {
398 for (KtTypeConstraint constraint : constraints) {
399 KtSimpleNameExpression parameterName = constraint.getSubjectTypeParameterName();
400 if (parameterName != null && parameterName.getText().equals(typeParameter.getName())) {
401 return true;
402 }
403 }
404 return false;
405 }
406
407 private void checkConstructorInInterface(KtClass klass) {
408 KtPrimaryConstructor primaryConstructor = klass.getPrimaryConstructor();
409 if (primaryConstructor != null) {
410 trace.report(CONSTRUCTOR_IN_INTERFACE.on(primaryConstructor));
411 }
412 }
413
414 private void checkMethodsOfAnyInInterface(ClassDescriptorWithResolutionScopes classDescriptor) {
415 for (CallableMemberDescriptor declaredCallableMember : classDescriptor.getDeclaredCallableMembers()) {
416 if (!(declaredCallableMember instanceof FunctionDescriptor)) continue;
417 FunctionDescriptor functionDescriptor = (FunctionDescriptor) declaredCallableMember;
418
419 PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
420 if (!(declaration instanceof KtNamedFunction)) continue;
421 KtNamedFunction functionDeclaration = (KtNamedFunction) declaration;
422
423 if (isHidingParentMemberIfPresent(declaredCallableMember)) continue;
424
425 if (isImplementingMethodOfAny(declaredCallableMember)) {
426 trace.report(METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE.on(functionDeclaration));
427 }
428 }
429 }
430
431 private static final Set<String> METHOD_OF_ANY_NAMES = ImmutableSet.of("toString", "hashCode", "equals");
432
433 private static boolean isImplementingMethodOfAny(CallableMemberDescriptor member) {
434 if (!METHOD_OF_ANY_NAMES.contains(member.getName().asString())) return false;
435 if (member.getModality() == Modality.ABSTRACT) return false;
436
437 return isImplementingMethodOfAnyInternal(member, new HashSet<ClassDescriptor>());
438 }
439
440 private static boolean isImplementingMethodOfAnyInternal(CallableMemberDescriptor member, Set<ClassDescriptor> visitedClasses) {
441 for (CallableMemberDescriptor overridden : member.getOverriddenDescriptors()) {
442 DeclarationDescriptor containingDeclaration = overridden.getContainingDeclaration();
443 if (!(containingDeclaration instanceof ClassDescriptor)) continue;
444 ClassDescriptor containingClass = (ClassDescriptor) containingDeclaration;
445 if (visitedClasses.contains(containingClass)) continue;
446
447 if (DescriptorUtils.getFqName(containingClass).equals(KotlinBuiltIns.FQ_NAMES.any)) {
448 return true;
449 }
450
451 if (isHidingParentMemberIfPresent(overridden)) continue;
452
453 visitedClasses.add(containingClass);
454
455 if (isImplementingMethodOfAnyInternal(overridden, visitedClasses)) {
456 return true;
457 }
458 }
459
460 return false;
461 }
462
463 private static boolean isHidingParentMemberIfPresent(CallableMemberDescriptor member) {
464 KtNamedDeclaration declaration = (KtNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(member);
465 if (declaration != null) {
466 KtModifierList modifierList = declaration.getModifierList();
467 return modifierList == null || !modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD);
468 }
469 return false;
470 }
471
472 private void checkAnnotationClassWithBody(KtClassOrObject classOrObject) {
473 if (classOrObject.getBody() != null) {
474 trace.report(ANNOTATION_CLASS_WITH_BODY.on(classOrObject.getBody()));
475 }
476 }
477
478 private void checkValOnAnnotationParameter(KtClass aClass) {
479 for (KtParameter parameter : aClass.getPrimaryConstructorParameters()) {
480 if (!parameter.hasValOrVar()) {
481 trace.report(MISSING_VAL_ON_ANNOTATION_PARAMETER.on(parameter));
482 }
483 }
484 }
485
486 private void checkOpenMembers(ClassDescriptorWithResolutionScopes classDescriptor) {
487 if (classCanHaveOpenMembers(classDescriptor)) return;
488
489 for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) {
490 if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) continue;
491 KtNamedDeclaration member = (KtNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor);
492 if (member != null && member.hasModifier(KtTokens.OPEN_KEYWORD)) {
493 trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member));
494 }
495 }
496 }
497
498 private void checkProperty(KtProperty property, PropertyDescriptor propertyDescriptor) {
499 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
500 if (containingDeclaration instanceof ClassDescriptor) {
501 checkPropertyAbstractness(property, propertyDescriptor, (ClassDescriptor) containingDeclaration);
502 }
503 checkPropertyLateInit(property, propertyDescriptor);
504 checkPropertyInitializer(property, propertyDescriptor);
505 checkAccessors(property, propertyDescriptor);
506 checkTypeParameterConstraints(property);
507 checkPropertyExposedType(property, propertyDescriptor);
508 checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor);
509 }
510
511 private void checkPropertyTypeParametersAreUsedInReceiverType(@NotNull PropertyDescriptor descriptor) {
512 for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) {
513 if (isTypeParameterUsedInReceiverType(typeParameter, descriptor)) continue;
514
515 PsiElement typeParameterPsi = DescriptorToSourceUtils.getSourceFromDescriptor(typeParameter);
516 if (typeParameterPsi instanceof KtTypeParameter) {
517 trace.report(TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER.on((KtTypeParameter) typeParameterPsi));
518 }
519 }
520 }
521
522 private static boolean isTypeParameterUsedInReceiverType(
523 @NotNull final TypeParameterDescriptor parameter,
524 @NotNull PropertyDescriptor descriptor
525 ) {
526 ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter();
527 if (receiverParameter == null) return false;
528
529 return TypeUtils.containsSpecialType(receiverParameter.getType(), new Function1<KotlinType, Boolean>() {
530 @Override
531 public Boolean invoke(KotlinType type) {
532 return parameter.equals(type.getConstructor().getDeclarationDescriptor());
533 }
534 });
535 }
536
537 private void checkPropertyLateInit(@NotNull KtCallableDeclaration property, @NotNull PropertyDescriptor propertyDescriptor) {
538 KtModifierList modifierList = property.getModifierList();
539 if (modifierList == null) return;
540 PsiElement modifier = modifierList.getModifier(KtTokens.LATEINIT_KEYWORD);
541 if (modifier == null) return;
542
543 if (!propertyDescriptor.isVar()) {
544 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is allowed only on mutable properties"));
545 }
546
547 boolean returnTypeIsNullable = true;
548 boolean returnTypeIsPrimitive = true;
549
550 KotlinType returnType = propertyDescriptor.getReturnType();
551 if (returnType != null) {
552 returnTypeIsNullable = TypeUtils.isNullableType(returnType);
553 returnTypeIsPrimitive = KotlinBuiltIns.isPrimitiveType(returnType);
554 }
555
556 if (returnTypeIsNullable) {
557 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on nullable properties"));
558 }
559
560 if (returnTypeIsPrimitive) {
561 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on primitive type properties"));
562 }
563
564 boolean isAbstract = propertyDescriptor.getModality() == Modality.ABSTRACT;
565 if (isAbstract) {
566 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on abstract properties"));
567 }
568
569 if (property instanceof KtParameter) {
570 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on primary constructor parameters"));
571 }
572
573 boolean hasDelegateExpressionOrInitializer = false;
574 if (property instanceof KtProperty) {
575 hasDelegateExpressionOrInitializer = ((KtProperty) property).hasDelegateExpressionOrInitializer();
576 if (hasDelegateExpressionOrInitializer) {
577 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier,
578 "is not allowed on properties with initializer or on delegated properties"));
579 }
580 }
581
582 PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
583 PropertySetterDescriptor setter = propertyDescriptor.getSetter();
584
585 boolean customGetterOrSetter = false;
586 if (getter != null) {
587 customGetterOrSetter = getter.hasBody();
588 }
589 if (setter != null) {
590 customGetterOrSetter |= setter.hasBody();
591 }
592
593 if (!hasDelegateExpressionOrInitializer && customGetterOrSetter) {
594 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties with a custom getter or setter"));
595 }
596
597 boolean hasBackingField =
598 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor));
599
600 if (!isAbstract && !customGetterOrSetter && !hasDelegateExpressionOrInitializer && !hasBackingField) {
601 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties without backing field"));
602 }
603
604 if (propertyDescriptor.getExtensionReceiverParameter() != null) {
605 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on extension properties"));
606 }
607 }
608
609 private void checkPropertyAbstractness(
610 @NotNull KtProperty property,
611 @NotNull PropertyDescriptor propertyDescriptor,
612 @NotNull ClassDescriptor classDescriptor
613 ) {
614 KtPropertyAccessor getter = property.getGetter();
615 KtPropertyAccessor setter = property.getSetter();
616 KtModifierList modifierList = property.getModifierList();
617
618 if (modifierList != null && modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) { //has abstract modifier
619 if (!classCanHaveAbstractMembers(classDescriptor)) {
620 String name = property.getName();
621 trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, name != null ? name : "", classDescriptor));
622 return;
623 }
624 if (classDescriptor.getKind() == ClassKind.INTERFACE) {
625 trace.report(ABSTRACT_MODIFIER_IN_INTERFACE.on(property));
626 }
627 }
628
629 if (propertyDescriptor.getModality() == Modality.ABSTRACT) {
630 KtExpression initializer = property.getInitializer();
631 if (initializer != null) {
632 trace.report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(initializer));
633 }
634 KtPropertyDelegate delegate = property.getDelegate();
635 if (delegate != null) {
636 trace.report(ABSTRACT_DELEGATED_PROPERTY.on(delegate));
637 }
638 if (getter != null && getter.hasBody()) {
639 trace.report(ABSTRACT_PROPERTY_WITH_GETTER.on(getter));
640 }
641 if (setter != null && setter.hasBody()) {
642 trace.report(ABSTRACT_PROPERTY_WITH_SETTER.on(setter));
643 }
644 }
645 }
646
647 private void checkPropertyInitializer(@NotNull KtProperty property, @NotNull PropertyDescriptor propertyDescriptor) {
648 KtPropertyAccessor getter = property.getGetter();
649 KtPropertyAccessor setter = property.getSetter();
650 boolean hasAccessorImplementation = (getter != null && getter.hasBody()) ||
651 (setter != null && setter.hasBody());
652
653 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
654 boolean inTrait = containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor)containingDeclaration).getKind() == ClassKind.INTERFACE;
655 if (propertyDescriptor.getModality() == Modality.ABSTRACT) {
656 if (!property.hasDelegateExpressionOrInitializer() && property.getTypeReference() == null) {
657 trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property));
658 }
659 if (inTrait && property.hasModifier(KtTokens.PRIVATE_KEYWORD) && !property.hasModifier(KtTokens.ABSTRACT_KEYWORD)) {
660 trace.report(PRIVATE_PROPERTY_IN_INTERFACE.on(property));
661 }
662 return;
663 }
664 KtExpression initializer = property.getInitializer();
665 KtPropertyDelegate delegate = property.getDelegate();
666 boolean backingFieldRequired =
667 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor));
668
669 if (inTrait && backingFieldRequired && hasAccessorImplementation) {
670 trace.report(BACKING_FIELD_IN_INTERFACE.on(property));
671 }
672
673 if (initializer == null && delegate == null) {
674 boolean error = false;
675 if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit() &&
676 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.IS_UNINITIALIZED, propertyDescriptor))) {
677 if (!(containingDeclaration instanceof ClassDescriptor) || hasAccessorImplementation) {
678 error = true;
679 trace.report(MUST_BE_INITIALIZED.on(property));
680 }
681 else {
682 error = true;
683 trace.report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property));
684 }
685 }
686 if (!error && property.getTypeReference() == null) {
687 trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property));
688 }
689 if (inTrait && property.hasModifier(KtTokens.FINAL_KEYWORD) && backingFieldRequired) {
690 trace.report(FINAL_PROPERTY_IN_INTERFACE.on(property));
691 }
692 return;
693 }
694
695 if (inTrait) {
696 if (delegate != null) {
697 trace.report(DELEGATED_PROPERTY_IN_INTERFACE.on(delegate));
698 }
699 else {
700 trace.report(PROPERTY_INITIALIZER_IN_INTERFACE.on(initializer));
701 }
702 }
703 else if (delegate == null) {
704 if (!backingFieldRequired) {
705 trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer));
706 }
707 else if (property.getReceiverTypeReference() != null) {
708 trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer));
709 }
710 }
711 }
712
713 private void checkMemberReceiverExposedType(@Nullable KtTypeReference typeReference, @NotNull CallableMemberDescriptor memberDescriptor) {
714 if (typeReference == null) return;
715 ReceiverParameterDescriptor receiverParameterDescriptor = memberDescriptor.getExtensionReceiverParameter();
716 if (receiverParameterDescriptor == null) return;
717 EffectiveVisibility memberVisibility = EffectiveVisibility.Companion.forMember(memberDescriptor);
718 EffectiveVisibility receiverTypeVisibility = EffectiveVisibility.Companion.forType(receiverParameterDescriptor.getType());
719 if (!receiverTypeVisibility.sameOrMorePermissive(memberVisibility)) {
720 trace.report(EXPOSED_RECEIVER_TYPE.on(typeReference, memberVisibility, receiverTypeVisibility));
721 }
722 }
723
724 private void checkPropertyExposedType(@NotNull KtProperty property, @NotNull PropertyDescriptor propertyDescriptor) {
725 EffectiveVisibility propertyVisibility = EffectiveVisibility.Companion.forMember(propertyDescriptor);
726 EffectiveVisibility typeVisibility = EffectiveVisibility.Companion.forType(propertyDescriptor.getType());
727 if (!typeVisibility.sameOrMorePermissive(propertyVisibility)) {
728 trace.report(EXPOSED_PROPERTY_TYPE.on(property, propertyVisibility, typeVisibility));
729 }
730 checkMemberReceiverExposedType(property.getReceiverTypeReference(), propertyDescriptor);
731 }
732
733 protected void checkFunction(KtNamedFunction function, SimpleFunctionDescriptor functionDescriptor) {
734 KtTypeParameterList typeParameterList = function.getTypeParameterList();
735 PsiElement nameIdentifier = function.getNameIdentifier();
736 if (typeParameterList != null && nameIdentifier != null &&
737 typeParameterList.getTextRange().getStartOffset() > nameIdentifier.getTextRange().getStartOffset()) {
738 trace.report(DEPRECATED_TYPE_PARAMETER_SYNTAX.on(typeParameterList));
739 }
740 checkTypeParameterConstraints(function);
741
742 DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration();
743 boolean hasAbstractModifier = function.hasModifier(KtTokens.ABSTRACT_KEYWORD);
744 boolean hasExternalModifier = function.hasModifier(KtTokens.EXTERNAL_KEYWORD);
745
746 if (containingDescriptor instanceof ClassDescriptor) {
747 ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor;
748 boolean inTrait = classDescriptor.getKind() == ClassKind.INTERFACE;
749 if (hasAbstractModifier && !classCanHaveAbstractMembers(classDescriptor)) {
750 trace.report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.getName().asString(), classDescriptor));
751 }
752 if (hasAbstractModifier && inTrait) {
753 trace.report(ABSTRACT_MODIFIER_IN_INTERFACE.on(function));
754 }
755 boolean hasBody = function.hasBody();
756 if (hasBody && hasAbstractModifier) {
757 trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor));
758 }
759 if (!hasBody && inTrait) {
760 if (function.hasModifier(KtTokens.FINAL_KEYWORD) && !hasExternalModifier) {
761 trace.report(FINAL_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor));
762 }
763 if (function.hasModifier(KtTokens.PRIVATE_KEYWORD)) {
764 trace.report(PRIVATE_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor));
765 }
766 }
767 if (!hasBody && !hasAbstractModifier && !hasExternalModifier && !inTrait) {
768 trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor));
769 }
770 return;
771 }
772 if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier) {
773 trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor));
774 }
775 if (TypeUtilsKt.isNothing(functionDescriptor.getReturnType()) && !function.hasDeclaredReturnType()) {
776 trace.report(IMPLICIT_NOTHING_RETURN_TYPE.on(function.getNameIdentifier() != null ? function.getNameIdentifier() : function));
777 }
778 checkFunctionExposedType(function, functionDescriptor);
779 }
780
781 private void checkFunctionExposedType(@NotNull KtFunction function, @NotNull FunctionDescriptor functionDescriptor) {
782 EffectiveVisibility functionVisibility = EffectiveVisibility.Companion.forMember(functionDescriptor);
783 if (!(function instanceof KtConstructor)) {
784 EffectiveVisibility returnTypeVisibility = EffectiveVisibility.Companion.forType(functionDescriptor.getReturnType());
785 if (!returnTypeVisibility.sameOrMorePermissive(functionVisibility)) {
786 PsiElement reportOn = function.getNameIdentifier();
787 if (reportOn == null) {
788 reportOn = function;
789 }
790 trace.report(EXPOSED_FUNCTION_RETURN_TYPE.on(reportOn, functionVisibility, returnTypeVisibility));
791 }
792 }
793 int i = 0;
794 for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
795 EffectiveVisibility typeVisibility = EffectiveVisibility.Companion.forType(parameterDescriptor.getType());
796 if (!typeVisibility.sameOrMorePermissive(functionVisibility) && i < function.getValueParameters().size()) {
797 trace.report(EXPOSED_PARAMETER_TYPE.on(function.getValueParameters().get(i), functionVisibility, typeVisibility));
798 }
799 i++;
800 }
801 checkMemberReceiverExposedType(function.getReceiverTypeReference(), functionDescriptor);
802 }
803
804 private void checkAccessors(@NotNull KtProperty property, @NotNull PropertyDescriptor propertyDescriptor) {
805 for (KtPropertyAccessor accessor : property.getAccessors()) {
806 PropertyAccessorDescriptor propertyAccessorDescriptor = accessor.isGetter() ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
807 assert propertyAccessorDescriptor != null : "No property accessor descriptor for " + property.getText();
808 modifiersChecker.checkModifiersForDeclaration(accessor, propertyAccessorDescriptor);
809 identifierChecker.checkDeclaration(accessor, trace);
810 }
811 checkAccessor(propertyDescriptor, property.getGetter(), propertyDescriptor.getGetter());
812 checkAccessor(propertyDescriptor, property.getSetter(), propertyDescriptor.getSetter());
813 }
814
815 private void reportVisibilityModifierDiagnostics(Collection<PsiElement> tokens, DiagnosticFactory0<PsiElement> diagnostic) {
816 for (PsiElement token : tokens) {
817 trace.report(diagnostic.on(token));
818 }
819 }
820
821 private void checkAccessor(
822 @NotNull PropertyDescriptor propertyDescriptor,
823 @Nullable KtPropertyAccessor accessor,
824 @Nullable PropertyAccessorDescriptor accessorDescriptor
825 ) {
826 if (accessor == null) return;
827 KtModifierList accessorModifierList = accessor.getModifierList();
828 if (accessorModifierList != null && accessorDescriptor != null) {
829 Map<KtModifierKeywordToken, PsiElement> tokens = modifiersChecker.getTokensCorrespondingToModifiers(accessorModifierList, Sets
830 .newHashSet(KtTokens.PUBLIC_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.PRIVATE_KEYWORD,
831 KtTokens.INTERNAL_KEYWORD));
832 if (accessor.isGetter()) {
833 if (accessorDescriptor.getVisibility() != propertyDescriptor.getVisibility()) {
834 reportVisibilityModifierDiagnostics(tokens.values(), Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY);
835 }
836 else {
837 reportVisibilityModifierDiagnostics(tokens.values(), Errors.REDUNDANT_MODIFIER_IN_GETTER);
838 }
839 }
840 else {
841 if (propertyDescriptor.getModality() == Modality.ABSTRACT
842 && accessorDescriptor.getVisibility() == Visibilities.PRIVATE
843 && propertyDescriptor.getVisibility() != Visibilities.PRIVATE) {
844 reportVisibilityModifierDiagnostics(tokens.values(), Errors.ACCESSOR_VISIBILITY_FOR_ABSTRACT_PROPERTY);
845 }
846 else if (propertyDescriptor.isLateInit() && accessorDescriptor.getVisibility() != propertyDescriptor.getVisibility()) {
847 reportVisibilityModifierDiagnostics(tokens.values(), Errors.SETTER_VISIBILITY_DIFFERS_FROM_LATEINIT_VISIBILITY);
848 }
849 }
850 }
851 }
852
853 private void checkEnumEntry(@NotNull KtEnumEntry enumEntry, @NotNull ClassDescriptor classDescriptor) {
854 DeclarationDescriptor declaration = classDescriptor.getContainingDeclaration();
855 if (DescriptorUtils.isEnumClass(declaration)) {
856 if (!enumEntry.hasInitializer() && !hasDefaultConstructor((ClassDescriptor) declaration)) {
857 trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry));
858 }
859 }
860 else {
861 assert DescriptorUtils.isInterface(declaration) : "Enum entry should be declared in enum class: " + classDescriptor;
862 }
863 }
864
865 private static boolean hasDefaultConstructor(@NotNull ClassDescriptor classDescriptor) {
866 for (ConstructorDescriptor constructor : classDescriptor.getConstructors()) {
867 if (constructor.getValueParameters().isEmpty()) return true;
868 }
869 return false;
870 }
871 }