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(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(@NotNull ClassDescriptor classDescriptor) { 188 Multimap<TypeConstructor, TypeProjection> multimap = SubstitutionUtils 189 .buildDeepSubstitutionMultimap(classDescriptor.getDefaultType()); 190 for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) { 191 Collection<TypeProjection> projections = entry.getValue(); 192 if (projections.size() > 1) { 193 TypeConstructor typeConstructor = entry.getKey(); 194 DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor(); 195 assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor; 196 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; 197 198 // Immediate arguments of supertypes cannot be projected 199 Set<KotlinType> conflictingTypes = Sets.newLinkedHashSet(); 200 for (TypeProjection projection : projections) { 201 conflictingTypes.add(projection.getType()); 202 } 203 removeDuplicateTypes(conflictingTypes); 204 if (conflictingTypes.size() > 1) { 205 DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration(); 206 assert containingDeclaration instanceof ClassDescriptor : containingDeclaration; 207 KtClassOrObject psiElement = (KtClassOrObject) DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor); 208 assert psiElement != null; 209 KtDelegationSpecifierList delegationSpecifierList = psiElement.getDelegationSpecifierList(); 210 assert delegationSpecifierList != null; 211 // trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + " has inconsistent values: " + conflictingTypes); 212 trace.report(INCONSISTENT_TYPE_PARAMETER_VALUES 213 .on(delegationSpecifierList, typeParameterDescriptor, (ClassDescriptor) containingDeclaration, 214 conflictingTypes)); 215 } 216 } 217 } 218 } 219 220 private void checkClassExposedType(@NotNull KtClassOrObject klass, @NotNull ClassDescriptor classDescriptor) { 221 checkExposedSupertypes(klass, classDescriptor); 222 checkExposedParameterBounds(klass, classDescriptor); 223 224 if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null && klass.getPrimaryConstructor() != null) { 225 checkFunctionExposedType(klass.getPrimaryConstructor(), classDescriptor.getUnsubstitutedPrimaryConstructor()); 226 } 227 } 228 229 private void checkExposedParameterBounds(@NotNull KtClassOrObject klass, @NotNull ClassDescriptor classDescriptor) { 230 EffectiveVisibility classVisibility = EffectiveVisibility.Companion.forClass(classDescriptor); 231 List<KtTypeParameter> typeParameterList = klass.getTypeParameters(); 232 int i = 0; 233 for (TypeParameterDescriptor typeParameterDescriptor : classDescriptor.getTypeConstructor().getParameters()) { 234 if (i >= typeParameterList.size()) return; 235 for (KotlinType upperBound : typeParameterDescriptor.getUpperBounds()) { 236 EffectiveVisibility upperBoundVisibility = EffectiveVisibility.Companion.forType(upperBound); 237 if (!upperBoundVisibility.sameOrMorePermissive(classVisibility)) { 238 KtTypeParameter typeParameter = typeParameterList.get(i); 239 trace.report(EXPOSED_TYPE_PARAMETER_BOUND.on(typeParameter, classVisibility, upperBoundVisibility)); 240 break; 241 } 242 } 243 i++; 244 } 245 } 246 247 private void checkExposedSupertypes(@NotNull KtClassOrObject klass, @NotNull ClassDescriptor classDescriptor) { 248 EffectiveVisibility classVisibility = EffectiveVisibility.Companion.forClass(classDescriptor); 249 boolean isInterface = classDescriptor.getKind() == ClassKind.INTERFACE; 250 List<KtDelegationSpecifier> delegationList = klass.getDelegationSpecifiers(); 251 int i = -1; 252 for (KotlinType superType : classDescriptor.getTypeConstructor().getSupertypes()) { 253 i++; 254 if (i >= delegationList.size()) return; 255 ClassDescriptor superDescriptor = TypeUtils.getClassDescriptor(superType); 256 if (superDescriptor == null) { 257 continue; 258 } 259 boolean superIsInterface = superDescriptor.getKind() == ClassKind.INTERFACE; 260 if (superIsInterface != isInterface) { 261 continue; 262 } 263 EffectiveVisibility superTypeVisibility = EffectiveVisibility.Companion.forType(superType); 264 if (!superTypeVisibility.sameOrMorePermissive(classVisibility)) { 265 if (isInterface) { 266 trace.report(EXPOSED_SUPER_INTERFACE.on(delegationList.get(i), classVisibility, superTypeVisibility)); 267 } 268 else { 269 trace.report(EXPOSED_SUPER_CLASS.on(delegationList.get(i), classVisibility, superTypeVisibility)); 270 } 271 } 272 } 273 } 274 275 private static void removeDuplicateTypes(Set<KotlinType> conflictingTypes) { 276 for (Iterator<KotlinType> iterator = conflictingTypes.iterator(); iterator.hasNext(); ) { 277 KotlinType type = iterator.next(); 278 for (KotlinType otherType : conflictingTypes) { 279 boolean subtypeOf = KotlinTypeChecker.DEFAULT.equalTypes(type, otherType); 280 if (type != otherType && subtypeOf) { 281 iterator.remove(); 282 break; 283 } 284 } 285 } 286 } 287 288 private void checkObject(KtObjectDeclaration declaration, ClassDescriptor classDescriptor) { 289 if (declaration.isLocal() && !declaration.isCompanion() && !declaration.isObjectLiteral()) { 290 trace.report(LOCAL_OBJECT_NOT_ALLOWED.on(declaration, classDescriptor)); 291 } 292 } 293 294 private void checkClass(BodiesResolveContext c, KtClass aClass, ClassDescriptorWithResolutionScopes classDescriptor) { 295 checkOpenMembers(classDescriptor); 296 checkTypeParameters(aClass); 297 checkTypeParameterConstraints(aClass); 298 299 if (aClass.isInterface()) { 300 checkConstructorInInterface(aClass); 301 checkMethodsOfAnyInInterface(classDescriptor); 302 if (aClass.isLocal() && !(classDescriptor.getContainingDeclaration() instanceof ClassDescriptor)) { 303 trace.report(LOCAL_INTERFACE_NOT_ALLOWED.on(aClass, classDescriptor)); 304 } 305 } 306 else if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) { 307 checkAnnotationClassWithBody(aClass); 308 checkValOnAnnotationParameter(aClass); 309 } 310 else if (aClass instanceof KtEnumEntry) { 311 checkEnumEntry((KtEnumEntry) aClass, classDescriptor); 312 } 313 for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) { 314 if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) continue; 315 KtNamedDeclaration member = (KtNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor); 316 if (member instanceof KtFunction && memberDescriptor instanceof FunctionDescriptor) { 317 checkFunctionExposedType((KtFunction) member, (FunctionDescriptor) memberDescriptor); 318 } 319 } 320 } 321 322 private void checkPrimaryConstructor(KtClassOrObject classOrObject, ClassDescriptor classDescriptor) { 323 ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); 324 KtPrimaryConstructor declaration = classOrObject.getPrimaryConstructor(); 325 if (primaryConstructor == null || declaration == null) return; 326 327 for (KtParameter parameter : declaration.getValueParameters()) { 328 PropertyDescriptor propertyDescriptor = trace.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); 329 if (propertyDescriptor != null) { 330 modifiersChecker.checkModifiersForDeclaration(parameter, propertyDescriptor); 331 checkPropertyLateInit(parameter, propertyDescriptor); 332 } 333 } 334 335 if (declaration.getModifierList() != null && !declaration.hasConstructorKeyword()) { 336 trace.report(MISSING_CONSTRUCTOR_KEYWORD.on(declaration.getModifierList())); 337 } 338 339 if (!(classOrObject instanceof KtClass)) { 340 trace.report(CONSTRUCTOR_IN_OBJECT.on(declaration)); 341 } 342 343 checkConstructorDeclaration(primaryConstructor, declaration); 344 } 345 346 private void checkTypeParameters(KtTypeParameterListOwner typeParameterListOwner) { 347 // TODO: Support annotation for type parameters 348 for (KtTypeParameter jetTypeParameter : typeParameterListOwner.getTypeParameters()) { 349 AnnotationResolver.reportUnsupportedAnnotationForTypeParameter(jetTypeParameter, trace); 350 351 TypeParameterDescriptor typeParameter = trace.get(TYPE_PARAMETER, jetTypeParameter); 352 if (typeParameter != null) { 353 DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter); 354 } 355 } 356 } 357 358 private void checkTypeParameterConstraints(KtTypeParameterListOwner typeParameterListOwner) { 359 List<KtTypeConstraint> constraints = typeParameterListOwner.getTypeConstraints(); 360 if (!constraints.isEmpty()) { 361 for (KtTypeParameter typeParameter : typeParameterListOwner.getTypeParameters()) { 362 if (typeParameter.getExtendsBound() != null && hasConstraints(typeParameter, constraints)) { 363 trace.report(MISPLACED_TYPE_PARAMETER_CONSTRAINTS.on(typeParameter)); 364 } 365 } 366 } 367 } 368 369 private static boolean hasConstraints(KtTypeParameter typeParameter, List<KtTypeConstraint> constraints) { 370 for (KtTypeConstraint constraint : constraints) { 371 KtSimpleNameExpression parameterName = constraint.getSubjectTypeParameterName(); 372 if (parameterName != null && parameterName.getText().equals(typeParameter.getName())) { 373 return true; 374 } 375 } 376 return false; 377 } 378 379 private void checkConstructorInInterface(KtClass klass) { 380 KtPrimaryConstructor primaryConstructor = klass.getPrimaryConstructor(); 381 if (primaryConstructor != null) { 382 trace.report(CONSTRUCTOR_IN_INTERFACE.on(primaryConstructor)); 383 } 384 } 385 386 private void checkMethodsOfAnyInInterface(ClassDescriptorWithResolutionScopes classDescriptor) { 387 for (CallableMemberDescriptor declaredCallableMember : classDescriptor.getDeclaredCallableMembers()) { 388 if (!(declaredCallableMember instanceof FunctionDescriptor)) continue; 389 FunctionDescriptor functionDescriptor = (FunctionDescriptor) declaredCallableMember; 390 391 PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor); 392 if (!(declaration instanceof KtNamedFunction)) continue; 393 KtNamedFunction functionDeclaration = (KtNamedFunction) declaration; 394 395 if (isHidingParentMemberIfPresent(declaredCallableMember)) continue; 396 397 if (isImplementingMethodOfAny(declaredCallableMember)) { 398 trace.report(METHOD_OF_ANY_IMPLEMENTED_IN_INTERFACE.on(functionDeclaration)); 399 } 400 } 401 } 402 403 private static final Set<String> METHOD_OF_ANY_NAMES = ImmutableSet.of("toString", "hashCode", "equals"); 404 405 private static boolean isImplementingMethodOfAny(CallableMemberDescriptor member) { 406 if (!METHOD_OF_ANY_NAMES.contains(member.getName().asString())) return false; 407 if (member.getModality() == Modality.ABSTRACT) return false; 408 409 return isImplementingMethodOfAnyInternal(member, new HashSet<ClassDescriptor>()); 410 } 411 412 private static boolean isImplementingMethodOfAnyInternal(CallableMemberDescriptor member, Set<ClassDescriptor> visitedClasses) { 413 for (CallableMemberDescriptor overridden : member.getOverriddenDescriptors()) { 414 DeclarationDescriptor containingDeclaration = overridden.getContainingDeclaration(); 415 if (!(containingDeclaration instanceof ClassDescriptor)) continue; 416 ClassDescriptor containingClass = (ClassDescriptor) containingDeclaration; 417 if (visitedClasses.contains(containingClass)) continue; 418 419 if (DescriptorUtils.getFqName(containingClass).equals(KotlinBuiltIns.FQ_NAMES.any)) { 420 return true; 421 } 422 423 if (isHidingParentMemberIfPresent(overridden)) continue; 424 425 visitedClasses.add(containingClass); 426 427 if (isImplementingMethodOfAnyInternal(overridden, visitedClasses)) { 428 return true; 429 } 430 } 431 432 return false; 433 } 434 435 private static boolean isHidingParentMemberIfPresent(CallableMemberDescriptor member) { 436 KtNamedDeclaration declaration = (KtNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(member); 437 if (declaration != null) { 438 KtModifierList modifierList = declaration.getModifierList(); 439 return modifierList == null || !modifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD); 440 } 441 return false; 442 } 443 444 private void checkAnnotationClassWithBody(KtClassOrObject classOrObject) { 445 if (classOrObject.getBody() != null) { 446 trace.report(ANNOTATION_CLASS_WITH_BODY.on(classOrObject.getBody())); 447 } 448 } 449 450 private void checkValOnAnnotationParameter(KtClass aClass) { 451 for (KtParameter parameter : aClass.getPrimaryConstructorParameters()) { 452 if (!parameter.hasValOrVar()) { 453 trace.report(MISSING_VAL_ON_ANNOTATION_PARAMETER.on(parameter)); 454 } 455 } 456 } 457 458 private void checkOpenMembers(ClassDescriptorWithResolutionScopes classDescriptor) { 459 if (classCanHaveOpenMembers(classDescriptor)) return; 460 461 for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) { 462 if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) continue; 463 KtNamedDeclaration member = (KtNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor); 464 if (member != null && member.hasModifier(KtTokens.OPEN_KEYWORD)) { 465 trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member)); 466 } 467 } 468 } 469 470 private void checkProperty(KtProperty property, PropertyDescriptor propertyDescriptor) { 471 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 472 if (containingDeclaration instanceof ClassDescriptor) { 473 checkPropertyAbstractness(property, propertyDescriptor, (ClassDescriptor) containingDeclaration); 474 } 475 checkPropertyLateInit(property, propertyDescriptor); 476 checkPropertyInitializer(property, propertyDescriptor); 477 checkAccessors(property, propertyDescriptor); 478 checkTypeParameterConstraints(property); 479 checkPropertyExposedType(property, propertyDescriptor); 480 checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor); 481 } 482 483 private void checkPropertyTypeParametersAreUsedInReceiverType(@NotNull PropertyDescriptor descriptor) { 484 for (TypeParameterDescriptor typeParameter : descriptor.getTypeParameters()) { 485 if (isTypeParameterUsedInReceiverType(typeParameter, descriptor)) continue; 486 487 PsiElement typeParameterPsi = DescriptorToSourceUtils.getSourceFromDescriptor(typeParameter); 488 if (typeParameterPsi instanceof KtTypeParameter) { 489 trace.report(TYPE_PARAMETER_OF_PROPERTY_NOT_USED_IN_RECEIVER.on((KtTypeParameter) typeParameterPsi)); 490 } 491 } 492 } 493 494 private static boolean isTypeParameterUsedInReceiverType( 495 @NotNull final TypeParameterDescriptor parameter, 496 @NotNull PropertyDescriptor descriptor 497 ) { 498 ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter(); 499 if (receiverParameter == null) return false; 500 501 return TypeUtils.containsSpecialType(receiverParameter.getType(), new Function1<KotlinType, Boolean>() { 502 @Override 503 public Boolean invoke(KotlinType type) { 504 return parameter.equals(type.getConstructor().getDeclarationDescriptor()); 505 } 506 }); 507 } 508 509 private void checkPropertyLateInit(@NotNull KtCallableDeclaration property, @NotNull PropertyDescriptor propertyDescriptor) { 510 KtModifierList modifierList = property.getModifierList(); 511 if (modifierList == null) return; 512 PsiElement modifier = modifierList.getModifier(KtTokens.LATEINIT_KEYWORD); 513 if (modifier == null) return; 514 515 if (!propertyDescriptor.isVar()) { 516 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is allowed only on mutable properties")); 517 } 518 519 boolean returnTypeIsNullable = true; 520 boolean returnTypeIsPrimitive = true; 521 522 KotlinType returnType = propertyDescriptor.getReturnType(); 523 if (returnType != null) { 524 returnTypeIsNullable = TypeUtils.isNullableType(returnType); 525 returnTypeIsPrimitive = KotlinBuiltIns.isPrimitiveType(returnType); 526 } 527 528 if (returnTypeIsNullable) { 529 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on nullable properties")); 530 } 531 532 if (returnTypeIsPrimitive) { 533 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on primitive type properties")); 534 } 535 536 boolean isAbstract = propertyDescriptor.getModality() == Modality.ABSTRACT; 537 if (isAbstract) { 538 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on abstract properties")); 539 } 540 541 if (property instanceof KtParameter) { 542 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on primary constructor parameters")); 543 } 544 545 boolean hasDelegateExpressionOrInitializer = false; 546 if (property instanceof KtProperty) { 547 hasDelegateExpressionOrInitializer = ((KtProperty) property).hasDelegateExpressionOrInitializer(); 548 if (hasDelegateExpressionOrInitializer) { 549 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, 550 "is not allowed on properties with initializer or on delegated properties")); 551 } 552 } 553 554 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 555 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 556 557 boolean customGetterOrSetter = false; 558 if (getter != null) { 559 customGetterOrSetter = getter.hasBody(); 560 } 561 if (setter != null) { 562 customGetterOrSetter |= setter.hasBody(); 563 } 564 565 if (!hasDelegateExpressionOrInitializer && customGetterOrSetter) { 566 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties with a custom getter or setter")); 567 } 568 569 boolean hasBackingField = 570 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)); 571 572 if (!isAbstract && !customGetterOrSetter && !hasDelegateExpressionOrInitializer && !hasBackingField) { 573 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on properties without backing field")); 574 } 575 576 if (propertyDescriptor.getExtensionReceiverParameter() != null) { 577 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier, "is not allowed on extension properties")); 578 } 579 } 580 581 private void checkPropertyAbstractness( 582 @NotNull KtProperty property, 583 @NotNull PropertyDescriptor propertyDescriptor, 584 @NotNull ClassDescriptor classDescriptor 585 ) { 586 KtPropertyAccessor getter = property.getGetter(); 587 KtPropertyAccessor setter = property.getSetter(); 588 KtModifierList modifierList = property.getModifierList(); 589 590 if (modifierList != null && modifierList.hasModifier(KtTokens.ABSTRACT_KEYWORD)) { //has abstract modifier 591 if (!classCanHaveAbstractMembers(classDescriptor)) { 592 String name = property.getName(); 593 trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, name != null ? name : "", classDescriptor)); 594 return; 595 } 596 if (classDescriptor.getKind() == ClassKind.INTERFACE) { 597 trace.report(ABSTRACT_MODIFIER_IN_INTERFACE.on(property)); 598 } 599 } 600 601 if (propertyDescriptor.getModality() == Modality.ABSTRACT) { 602 KtExpression initializer = property.getInitializer(); 603 if (initializer != null) { 604 trace.report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(initializer)); 605 } 606 KtPropertyDelegate delegate = property.getDelegate(); 607 if (delegate != null) { 608 trace.report(ABSTRACT_DELEGATED_PROPERTY.on(delegate)); 609 } 610 if (getter != null && getter.hasBody()) { 611 trace.report(ABSTRACT_PROPERTY_WITH_GETTER.on(getter)); 612 } 613 if (setter != null && setter.hasBody()) { 614 trace.report(ABSTRACT_PROPERTY_WITH_SETTER.on(setter)); 615 } 616 } 617 } 618 619 private void checkPropertyInitializer(@NotNull KtProperty property, @NotNull PropertyDescriptor propertyDescriptor) { 620 KtPropertyAccessor getter = property.getGetter(); 621 KtPropertyAccessor setter = property.getSetter(); 622 boolean hasAccessorImplementation = (getter != null && getter.hasBody()) || 623 (setter != null && setter.hasBody()); 624 625 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 626 boolean inTrait = containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor)containingDeclaration).getKind() == ClassKind.INTERFACE; 627 if (propertyDescriptor.getModality() == Modality.ABSTRACT) { 628 if (!property.hasDelegateExpressionOrInitializer() && property.getTypeReference() == null) { 629 trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property)); 630 } 631 if (inTrait && property.hasModifier(KtTokens.PRIVATE_KEYWORD) && !property.hasModifier(KtTokens.ABSTRACT_KEYWORD)) { 632 trace.report(PRIVATE_PROPERTY_IN_INTERFACE.on(property)); 633 } 634 return; 635 } 636 KtExpression initializer = property.getInitializer(); 637 KtPropertyDelegate delegate = property.getDelegate(); 638 boolean backingFieldRequired = 639 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)); 640 641 if (inTrait && backingFieldRequired && hasAccessorImplementation) { 642 trace.report(BACKING_FIELD_IN_INTERFACE.on(property)); 643 } 644 645 if (initializer == null && delegate == null) { 646 boolean error = false; 647 if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit() && 648 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.IS_UNINITIALIZED, propertyDescriptor))) { 649 if (!(containingDeclaration instanceof ClassDescriptor) || hasAccessorImplementation) { 650 error = true; 651 trace.report(MUST_BE_INITIALIZED.on(property)); 652 } 653 else { 654 error = true; 655 trace.report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property)); 656 } 657 } 658 if (!error && property.getTypeReference() == null) { 659 trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property)); 660 } 661 if (inTrait && property.hasModifier(KtTokens.FINAL_KEYWORD) && backingFieldRequired) { 662 trace.report(FINAL_PROPERTY_IN_INTERFACE.on(property)); 663 } 664 return; 665 } 666 667 if (inTrait) { 668 if (delegate != null) { 669 trace.report(DELEGATED_PROPERTY_IN_INTERFACE.on(delegate)); 670 } 671 else { 672 trace.report(PROPERTY_INITIALIZER_IN_INTERFACE.on(initializer)); 673 } 674 } 675 else if (delegate == null) { 676 if (!backingFieldRequired) { 677 trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer)); 678 } 679 else if (property.getReceiverTypeReference() != null) { 680 trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer)); 681 } 682 } 683 } 684 685 private void checkMemberReceiverExposedType(@Nullable KtTypeReference typeReference, @NotNull CallableMemberDescriptor memberDescriptor) { 686 if (typeReference == null) return; 687 ReceiverParameterDescriptor receiverParameterDescriptor = memberDescriptor.getExtensionReceiverParameter(); 688 if (receiverParameterDescriptor == null) return; 689 EffectiveVisibility memberVisibility = EffectiveVisibility.Companion.forMember(memberDescriptor); 690 EffectiveVisibility receiverTypeVisibility = EffectiveVisibility.Companion.forType(receiverParameterDescriptor.getType()); 691 if (!receiverTypeVisibility.sameOrMorePermissive(memberVisibility)) { 692 trace.report(EXPOSED_RECEIVER_TYPE.on(typeReference, memberVisibility, receiverTypeVisibility)); 693 } 694 } 695 696 private void checkPropertyExposedType(@NotNull KtProperty property, @NotNull PropertyDescriptor propertyDescriptor) { 697 EffectiveVisibility propertyVisibility = EffectiveVisibility.Companion.forMember(propertyDescriptor); 698 EffectiveVisibility typeVisibility = EffectiveVisibility.Companion.forType(propertyDescriptor.getType()); 699 if (!typeVisibility.sameOrMorePermissive(propertyVisibility)) { 700 trace.report(EXPOSED_PROPERTY_TYPE.on(property, propertyVisibility, typeVisibility)); 701 } 702 checkMemberReceiverExposedType(property.getReceiverTypeReference(), propertyDescriptor); 703 } 704 705 protected void checkFunction(KtNamedFunction function, SimpleFunctionDescriptor functionDescriptor) { 706 KtTypeParameterList typeParameterList = function.getTypeParameterList(); 707 PsiElement nameIdentifier = function.getNameIdentifier(); 708 if (typeParameterList != null && nameIdentifier != null && 709 typeParameterList.getTextRange().getStartOffset() > nameIdentifier.getTextRange().getStartOffset()) { 710 trace.report(DEPRECATED_TYPE_PARAMETER_SYNTAX.on(typeParameterList)); 711 } 712 checkTypeParameterConstraints(function); 713 714 DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration(); 715 boolean hasAbstractModifier = function.hasModifier(KtTokens.ABSTRACT_KEYWORD); 716 boolean hasExternalModifier = function.hasModifier(KtTokens.EXTERNAL_KEYWORD); 717 718 if (containingDescriptor instanceof ClassDescriptor) { 719 ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor; 720 boolean inTrait = classDescriptor.getKind() == ClassKind.INTERFACE; 721 if (hasAbstractModifier && !classCanHaveAbstractMembers(classDescriptor)) { 722 trace.report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.getName().asString(), classDescriptor)); 723 } 724 if (hasAbstractModifier && inTrait) { 725 trace.report(ABSTRACT_MODIFIER_IN_INTERFACE.on(function)); 726 } 727 boolean hasBody = function.hasBody(); 728 if (hasBody && hasAbstractModifier) { 729 trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor)); 730 } 731 if (!hasBody && inTrait) { 732 if (function.hasModifier(KtTokens.FINAL_KEYWORD) && !hasExternalModifier) { 733 trace.report(FINAL_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); 734 } 735 if (function.hasModifier(KtTokens.PRIVATE_KEYWORD)) { 736 trace.report(PRIVATE_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); 737 } 738 } 739 if (!hasBody && !hasAbstractModifier && !hasExternalModifier && !inTrait) { 740 trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); 741 } 742 return; 743 } 744 if (!function.hasBody() && !hasAbstractModifier && !hasExternalModifier) { 745 trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor)); 746 } 747 if (TypeUtilsKt.isNothing(functionDescriptor.getReturnType()) && !function.hasDeclaredReturnType()) { 748 trace.report(IMPLICIT_NOTHING_RETURN_TYPE.on(function.getNameIdentifier() != null ? function.getNameIdentifier() : function)); 749 } 750 checkFunctionExposedType(function, functionDescriptor); 751 } 752 753 private void checkFunctionExposedType(@NotNull KtFunction function, @NotNull FunctionDescriptor functionDescriptor) { 754 EffectiveVisibility functionVisibility = EffectiveVisibility.Companion.forMember(functionDescriptor); 755 if (!(function instanceof KtConstructor)) { 756 EffectiveVisibility returnTypeVisibility = EffectiveVisibility.Companion.forType(functionDescriptor.getReturnType()); 757 if (!returnTypeVisibility.sameOrMorePermissive(functionVisibility)) { 758 PsiElement reportOn = function.getNameIdentifier(); 759 if (reportOn == null) { 760 reportOn = function; 761 } 762 trace.report(EXPOSED_FUNCTION_RETURN_TYPE.on(reportOn, functionVisibility, returnTypeVisibility)); 763 } 764 } 765 int i = 0; 766 for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) { 767 EffectiveVisibility typeVisibility = EffectiveVisibility.Companion.forType(parameterDescriptor.getType()); 768 if (!typeVisibility.sameOrMorePermissive(functionVisibility) && i < function.getValueParameters().size()) { 769 trace.report(EXPOSED_PARAMETER_TYPE.on(function.getValueParameters().get(i), functionVisibility, typeVisibility)); 770 } 771 i++; 772 } 773 checkMemberReceiverExposedType(function.getReceiverTypeReference(), functionDescriptor); 774 } 775 776 private void checkAccessors(@NotNull KtProperty property, @NotNull PropertyDescriptor propertyDescriptor) { 777 for (KtPropertyAccessor accessor : property.getAccessors()) { 778 PropertyAccessorDescriptor propertyAccessorDescriptor = accessor.isGetter() ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter(); 779 assert propertyAccessorDescriptor != null : "No property accessor descriptor for " + property.getText(); 780 modifiersChecker.checkModifiersForDeclaration(accessor, propertyAccessorDescriptor); 781 identifierChecker.checkDeclaration(accessor, trace); 782 } 783 checkAccessor(propertyDescriptor, property.getGetter(), propertyDescriptor.getGetter()); 784 checkAccessor(propertyDescriptor, property.getSetter(), propertyDescriptor.getSetter()); 785 } 786 787 private void reportVisibilityModifierDiagnostics(Collection<PsiElement> tokens, DiagnosticFactory0<PsiElement> diagnostic) { 788 for (PsiElement token : tokens) { 789 trace.report(diagnostic.on(token)); 790 } 791 } 792 793 private void checkAccessor( 794 @NotNull PropertyDescriptor propertyDescriptor, 795 @Nullable KtPropertyAccessor accessor, 796 @Nullable PropertyAccessorDescriptor accessorDescriptor 797 ) { 798 if (accessor == null) return; 799 KtModifierList accessorModifierList = accessor.getModifierList(); 800 if (accessorModifierList != null && accessorDescriptor != null) { 801 Map<KtModifierKeywordToken, PsiElement> tokens = modifiersChecker.getTokensCorrespondingToModifiers(accessorModifierList, Sets 802 .newHashSet(KtTokens.PUBLIC_KEYWORD, KtTokens.PROTECTED_KEYWORD, KtTokens.PRIVATE_KEYWORD, 803 KtTokens.INTERNAL_KEYWORD)); 804 if (propertyDescriptor.getModality() == Modality.ABSTRACT && accessorDescriptor.getVisibility() != propertyDescriptor.getVisibility()) { 805 reportVisibilityModifierDiagnostics(tokens.values(), Errors.ACCESSOR_VISIBILITY_FOR_ABSTRACT_PROPERTY); 806 } 807 else if (accessor.isGetter()) { 808 if (accessorDescriptor.getVisibility() != propertyDescriptor.getVisibility()) { 809 reportVisibilityModifierDiagnostics(tokens.values(), Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY); 810 } 811 else { 812 reportVisibilityModifierDiagnostics(tokens.values(), Errors.REDUNDANT_MODIFIER_IN_GETTER); 813 } 814 } 815 else if (accessorDescriptor.getVisibility() == Visibilities.PRIVATE 816 && propertyDescriptor.getVisibility() != Visibilities.PRIVATE 817 && propertyDescriptor.isLateInit()) { 818 reportVisibilityModifierDiagnostics(tokens.values(), Errors.PRIVATE_SETTER_ON_NON_PRIVATE_LATE_INIT_VAR); 819 } 820 } 821 } 822 823 private void checkEnumEntry(@NotNull KtEnumEntry enumEntry, @NotNull ClassDescriptor classDescriptor) { 824 DeclarationDescriptor declaration = classDescriptor.getContainingDeclaration(); 825 if (DescriptorUtils.isEnumClass(declaration)) { 826 ClassDescriptor enumClass = (ClassDescriptor) declaration; 827 828 if (!enumEntry.hasInitializer() && !DescriptorUtils.hasDefaultConstructor(enumClass)) { 829 trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry)); 830 } 831 } 832 else { 833 assert DescriptorUtils.isInterface(declaration) : "Enum entry should be declared in enum class: " + 834 classDescriptor + " " + 835 classDescriptor.getKind(); 836 } 837 } 838 839 }