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 }