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.Multimap; 020 import com.google.common.collect.Sets; 021 import com.intellij.psi.PsiElement; 022 import org.jetbrains.annotations.NotNull; 023 import org.jetbrains.annotations.Nullable; 024 import org.jetbrains.kotlin.builtins.KotlinBuiltIns; 025 import org.jetbrains.kotlin.descriptors.*; 026 import org.jetbrains.kotlin.diagnostics.Errors; 027 import org.jetbrains.kotlin.lexer.JetModifierKeywordToken; 028 import org.jetbrains.kotlin.lexer.JetTokens; 029 import org.jetbrains.kotlin.psi.*; 030 import org.jetbrains.kotlin.types.*; 031 import org.jetbrains.kotlin.types.checker.JetTypeChecker; 032 033 import java.util.Collection; 034 import java.util.Iterator; 035 import java.util.Map; 036 import java.util.Set; 037 038 import static org.jetbrains.kotlin.diagnostics.Errors.*; 039 import static org.jetbrains.kotlin.resolve.BindingContext.TYPE; 040 import static org.jetbrains.kotlin.resolve.BindingContext.TYPE_PARAMETER; 041 import static org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveAbstractMembers; 042 import static org.jetbrains.kotlin.resolve.DescriptorUtils.classCanHaveOpenMembers; 043 044 public class DeclarationsChecker { 045 @NotNull private final BindingTrace trace; 046 @NotNull private final ModifiersChecker.ModifiersCheckingProcedure modifiersChecker; 047 @NotNull private final DescriptorResolver descriptorResolver; 048 @NotNull private final AnnotationChecker annotationChecker; 049 050 public DeclarationsChecker( 051 @NotNull DescriptorResolver descriptorResolver, 052 @NotNull ModifiersChecker modifiersChecker, 053 @NotNull AnnotationChecker annotationChecker, 054 @NotNull BindingTrace trace 055 ) { 056 this.descriptorResolver = descriptorResolver; 057 this.modifiersChecker = modifiersChecker.withTrace(trace); 058 this.annotationChecker = annotationChecker; 059 this.trace = trace; 060 } 061 062 public void process(@NotNull BodiesResolveContext bodiesResolveContext) { 063 for (JetFile file : bodiesResolveContext.getFiles()) { 064 checkModifiersAndAnnotationsInPackageDirective(file); 065 annotationChecker.check(file, trace, null); 066 } 067 068 Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes = bodiesResolveContext.getDeclaredClasses(); 069 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : classes.entrySet()) { 070 JetClassOrObject classOrObject = entry.getKey(); 071 ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue(); 072 073 checkSupertypesForConsistency(classDescriptor); 074 checkTypesInClassHeader(classOrObject); 075 076 if (classOrObject instanceof JetClass) { 077 JetClass jetClass = (JetClass) classOrObject; 078 checkClass(bodiesResolveContext, jetClass, classDescriptor); 079 descriptorResolver.checkNamesInConstraints( 080 jetClass, classDescriptor, classDescriptor.getScopeForClassHeaderResolution(), trace); 081 } 082 else if (classOrObject instanceof JetObjectDeclaration) { 083 checkObject((JetObjectDeclaration) classOrObject, classDescriptor); 084 } 085 086 checkPrimaryConstructor(classOrObject, classDescriptor); 087 088 modifiersChecker.checkModifiersForDeclaration(classOrObject, classDescriptor); 089 } 090 091 Map<JetNamedFunction, SimpleFunctionDescriptor> functions = bodiesResolveContext.getFunctions(); 092 for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : functions.entrySet()) { 093 JetNamedFunction function = entry.getKey(); 094 SimpleFunctionDescriptor functionDescriptor = entry.getValue(); 095 096 checkFunction(function, functionDescriptor); 097 modifiersChecker.checkModifiersForDeclaration(function, functionDescriptor); 098 } 099 100 Map<JetProperty, PropertyDescriptor> properties = bodiesResolveContext.getProperties(); 101 for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) { 102 JetProperty property = entry.getKey(); 103 PropertyDescriptor propertyDescriptor = entry.getValue(); 104 105 checkProperty(property, propertyDescriptor); 106 modifiersChecker.checkModifiersForDeclaration(property, propertyDescriptor); 107 } 108 109 for (Map.Entry<JetSecondaryConstructor, ConstructorDescriptor> entry : bodiesResolveContext.getSecondaryConstructors().entrySet()) { 110 ConstructorDescriptor constructorDescriptor = entry.getValue(); 111 JetSecondaryConstructor declaration = entry.getKey(); 112 checkConstructorDeclaration(constructorDescriptor, declaration); 113 } 114 115 } 116 117 private void checkConstructorDeclaration(ConstructorDescriptor constructorDescriptor, JetDeclaration declaration) { 118 modifiersChecker.checkModifiersForDeclaration(declaration, constructorDescriptor); 119 } 120 121 private void checkModifiersAndAnnotationsInPackageDirective(JetFile file) { 122 JetPackageDirective packageDirective = file.getPackageDirective(); 123 if (packageDirective == null) return; 124 125 JetModifierList modifierList = packageDirective.getModifierList(); 126 if (modifierList == null) return; 127 128 for (JetAnnotationEntry annotationEntry : modifierList.getAnnotationEntries()) { 129 JetConstructorCalleeExpression calleeExpression = annotationEntry.getCalleeExpression(); 130 if (calleeExpression != null) { 131 JetReferenceExpression reference = calleeExpression.getConstructorReferenceExpression(); 132 if (reference != null) { 133 trace.report(UNRESOLVED_REFERENCE.on(reference, reference)); 134 } 135 } 136 } 137 annotationChecker.check(packageDirective, trace, null); 138 ModifierCheckerCore.INSTANCE$.check(packageDirective, trace, null); 139 } 140 141 private void checkTypesInClassHeader(@NotNull JetClassOrObject classOrObject) { 142 for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) { 143 checkBoundsForTypeInClassHeader(delegationSpecifier.getTypeReference()); 144 } 145 146 if (!(classOrObject instanceof JetClass)) return; 147 JetClass jetClass = (JetClass) classOrObject; 148 149 for (JetTypeParameter jetTypeParameter : jetClass.getTypeParameters()) { 150 checkBoundsForTypeInClassHeader(jetTypeParameter.getExtendsBound()); 151 checkFinalUpperBounds(jetTypeParameter.getExtendsBound()); 152 } 153 154 for (JetTypeConstraint constraint : jetClass.getTypeConstraints()) { 155 checkBoundsForTypeInClassHeader(constraint.getBoundTypeReference()); 156 checkFinalUpperBounds(constraint.getBoundTypeReference()); 157 } 158 } 159 160 private void checkBoundsForTypeInClassHeader(@Nullable JetTypeReference typeReference) { 161 if (typeReference != null) { 162 JetType type = trace.getBindingContext().get(TYPE, typeReference); 163 if (type != null) { 164 DescriptorResolver.checkBounds(typeReference, type, trace); 165 } 166 } 167 } 168 169 private void checkFinalUpperBounds(@Nullable JetTypeReference typeReference) { 170 if (typeReference != null) { 171 JetType type = trace.getBindingContext().get(TYPE, typeReference); 172 if (type != null) { 173 DescriptorResolver.checkUpperBoundType(typeReference, type, trace); 174 } 175 } 176 } 177 178 private void checkSupertypesForConsistency(@NotNull ClassDescriptor classDescriptor) { 179 Multimap<TypeConstructor, TypeProjection> multimap = SubstitutionUtils 180 .buildDeepSubstitutionMultimap(classDescriptor.getDefaultType()); 181 for (Map.Entry<TypeConstructor, Collection<TypeProjection>> entry : multimap.asMap().entrySet()) { 182 Collection<TypeProjection> projections = entry.getValue(); 183 if (projections.size() > 1) { 184 TypeConstructor typeConstructor = entry.getKey(); 185 DeclarationDescriptor declarationDescriptor = typeConstructor.getDeclarationDescriptor(); 186 assert declarationDescriptor instanceof TypeParameterDescriptor : declarationDescriptor; 187 TypeParameterDescriptor typeParameterDescriptor = (TypeParameterDescriptor) declarationDescriptor; 188 189 // Immediate arguments of supertypes cannot be projected 190 Set<JetType> conflictingTypes = Sets.newLinkedHashSet(); 191 for (TypeProjection projection : projections) { 192 conflictingTypes.add(projection.getType()); 193 } 194 removeDuplicateTypes(conflictingTypes); 195 if (conflictingTypes.size() > 1) { 196 DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration(); 197 assert containingDeclaration instanceof ClassDescriptor : containingDeclaration; 198 JetClassOrObject psiElement = (JetClassOrObject) DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor); 199 assert psiElement != null; 200 JetDelegationSpecifierList delegationSpecifierList = psiElement.getDelegationSpecifierList(); 201 assert delegationSpecifierList != null; 202 // trace.getErrorHandler().genericError(delegationSpecifierList.getNode(), "Type parameter " + typeParameterDescriptor.getName() + " of " + containingDeclaration.getName() + " has inconsistent values: " + conflictingTypes); 203 trace.report(INCONSISTENT_TYPE_PARAMETER_VALUES 204 .on(delegationSpecifierList, typeParameterDescriptor, (ClassDescriptor) containingDeclaration, 205 conflictingTypes)); 206 } 207 } 208 } 209 } 210 211 private static void removeDuplicateTypes(Set<JetType> conflictingTypes) { 212 for (Iterator<JetType> iterator = conflictingTypes.iterator(); iterator.hasNext(); ) { 213 JetType type = iterator.next(); 214 for (JetType otherType : conflictingTypes) { 215 boolean subtypeOf = JetTypeChecker.DEFAULT.equalTypes(type, otherType); 216 if (type != otherType && subtypeOf) { 217 iterator.remove(); 218 break; 219 } 220 } 221 } 222 } 223 224 private void checkObject(JetObjectDeclaration declaration, ClassDescriptor classDescriptor) { 225 if (declaration.isLocal() && !declaration.isCompanion() && !declaration.isObjectLiteral()) { 226 trace.report(LOCAL_OBJECT_NOT_ALLOWED.on(declaration, classDescriptor)); 227 } 228 } 229 230 private void checkClass(BodiesResolveContext c, JetClass aClass, ClassDescriptorWithResolutionScopes classDescriptor) { 231 checkOpenMembers(classDescriptor); 232 checkTypeParameters(aClass); 233 234 if (aClass.isInterface()) { 235 checkConstructorInTrait(aClass); 236 } 237 else if (classDescriptor.getKind() == ClassKind.ANNOTATION_CLASS) { 238 checkAnnotationClassWithBody(aClass); 239 checkValOnAnnotationParameter(aClass); 240 } 241 else if (aClass instanceof JetEnumEntry) { 242 checkEnumEntry((JetEnumEntry) aClass, classDescriptor); 243 } 244 } 245 246 private void checkPrimaryConstructor(JetClassOrObject classOrObject, ClassDescriptor classDescriptor) { 247 ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); 248 JetPrimaryConstructor declaration = classOrObject.getPrimaryConstructor(); 249 if (primaryConstructor == null || declaration == null) return; 250 251 for (JetParameter parameter : declaration.getValueParameters()) { 252 PropertyDescriptor propertyDescriptor = trace.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); 253 if (propertyDescriptor != null) { 254 modifiersChecker.checkModifiersForDeclaration(parameter, propertyDescriptor); 255 checkPropertyLateInit(parameter, propertyDescriptor); 256 } 257 } 258 259 if (declaration.getModifierList() != null && !declaration.hasConstructorKeyword()) { 260 trace.report(MISSING_CONSTRUCTOR_KEYWORD.on(declaration.getModifierList())); 261 } 262 263 if (!(classOrObject instanceof JetClass)) { 264 trace.report(CONSTRUCTOR_IN_OBJECT.on(declaration)); 265 } 266 267 checkConstructorDeclaration(primaryConstructor, declaration); 268 } 269 270 private void checkTypeParameters(JetTypeParameterListOwner typeParameterListOwner) { 271 // TODO: Support annotation for type parameters 272 for (JetTypeParameter jetTypeParameter : typeParameterListOwner.getTypeParameters()) { 273 AnnotationResolver.reportUnsupportedAnnotationForTypeParameter(jetTypeParameter, trace); 274 275 TypeParameterDescriptor typeParameter = trace.get(TYPE_PARAMETER, jetTypeParameter); 276 if (typeParameter != null) { 277 DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter); 278 } 279 annotationChecker.check(jetTypeParameter, trace, null); 280 } 281 } 282 283 private void checkConstructorInTrait(JetClass klass) { 284 JetPrimaryConstructor primaryConstructor = klass.getPrimaryConstructor(); 285 if (primaryConstructor != null) { 286 trace.report(CONSTRUCTOR_IN_TRAIT.on(primaryConstructor)); 287 } 288 } 289 290 private void checkAnnotationClassWithBody(JetClassOrObject classOrObject) { 291 if (classOrObject.getBody() != null) { 292 trace.report(ANNOTATION_CLASS_WITH_BODY.on(classOrObject.getBody())); 293 } 294 } 295 296 private void checkValOnAnnotationParameter(JetClass aClass) { 297 for (JetParameter parameter : aClass.getPrimaryConstructorParameters()) { 298 if (!parameter.hasValOrVar()) { 299 trace.report(MISSING_VAL_ON_ANNOTATION_PARAMETER.on(parameter)); 300 } 301 } 302 } 303 304 private void checkOpenMembers(ClassDescriptorWithResolutionScopes classDescriptor) { 305 if (classCanHaveOpenMembers(classDescriptor)) return; 306 307 for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) { 308 if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) continue; 309 JetNamedDeclaration member = (JetNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor); 310 if (member != null && member.hasModifier(JetTokens.OPEN_KEYWORD)) { 311 trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member)); 312 } 313 } 314 } 315 316 private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) { 317 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 318 if (containingDeclaration instanceof ClassDescriptor) { 319 checkPropertyAbstractness(property, propertyDescriptor, (ClassDescriptor) containingDeclaration); 320 } 321 checkPropertyLateInit(property, propertyDescriptor); 322 checkPropertyInitializer(property, propertyDescriptor); 323 checkAccessors(property, propertyDescriptor); 324 } 325 326 private void checkPropertyLateInit(@NotNull JetCallableDeclaration property, @NotNull PropertyDescriptor propertyDescriptor) { 327 JetModifierList modifierList = property.getModifierList(); 328 if (modifierList == null) return; 329 PsiElement modifier = modifierList.getModifier(JetTokens.LATE_INIT_KEYWORD); 330 if (modifier == null) return; 331 332 if (!propertyDescriptor.isVar()) { 333 trace.report(INAPPLICABLE_LATEINIT_MODIFIER_IMMUTABLE.on(modifier)); 334 return; 335 } 336 337 boolean returnTypeIsNullable = true; 338 boolean returnTypeIsPrimitive = true; 339 340 JetType returnType = propertyDescriptor.getReturnType(); 341 if (returnType != null) { 342 returnTypeIsNullable = TypeUtils.isNullableType(returnType); 343 returnTypeIsPrimitive = KotlinBuiltIns.isPrimitiveType(returnType); 344 } 345 346 if (returnTypeIsNullable) { 347 trace.report(INAPPLICABLE_LATEINIT_MODIFIER_NULLABLE.on(modifier)); 348 return; 349 } 350 351 if (propertyDescriptor.getModality() == Modality.ABSTRACT) { 352 trace.report(INAPPLICABLE_LATEINIT_MODIFIER_ABSTRACT_PROPERTY.on(modifier)); 353 return; 354 } 355 356 if (property instanceof JetParameter) { 357 trace.report(INAPPLICABLE_LATEINIT_MODIFIER_PRIMARY_CONSTRUCTOR_PARAMETER.on(modifier)); 358 return; 359 } 360 361 boolean hasBackingField = 362 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)); 363 364 boolean hasDelegateOrInitializer = false; 365 366 if (property instanceof JetProperty) { 367 hasDelegateOrInitializer = ((JetProperty) property).hasDelegateExpressionOrInitializer(); 368 } 369 370 PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); 371 PropertySetterDescriptor setter = propertyDescriptor.getSetter(); 372 373 boolean customGetterOrSetter = false; 374 if (getter != null) { 375 customGetterOrSetter = getter.hasBody(); 376 } 377 if (setter != null) { 378 customGetterOrSetter |= setter.hasBody(); 379 } 380 381 if (!hasBackingField || hasDelegateOrInitializer || customGetterOrSetter 382 || returnTypeIsPrimitive || propertyDescriptor.getExtensionReceiverParameter() != null) { 383 trace.report(INAPPLICABLE_LATEINIT_MODIFIER.on(modifier)); 384 } 385 } 386 387 private void checkPropertyAbstractness( 388 @NotNull JetProperty property, 389 @NotNull PropertyDescriptor propertyDescriptor, 390 @NotNull ClassDescriptor classDescriptor 391 ) { 392 JetPropertyAccessor getter = property.getGetter(); 393 JetPropertyAccessor setter = property.getSetter(); 394 JetModifierList modifierList = property.getModifierList(); 395 396 if (modifierList != null && modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { //has abstract modifier 397 if (!classCanHaveAbstractMembers(classDescriptor)) { 398 String name = property.getName(); 399 trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, name != null ? name : "", classDescriptor)); 400 return; 401 } 402 if (classDescriptor.getKind() == ClassKind.INTERFACE) { 403 trace.report(ABSTRACT_MODIFIER_IN_TRAIT.on(property)); 404 } 405 } 406 407 if (propertyDescriptor.getModality() == Modality.ABSTRACT) { 408 JetExpression initializer = property.getInitializer(); 409 if (initializer != null) { 410 trace.report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(initializer)); 411 } 412 JetPropertyDelegate delegate = property.getDelegate(); 413 if (delegate != null) { 414 trace.report(ABSTRACT_DELEGATED_PROPERTY.on(delegate)); 415 } 416 if (getter != null && getter.hasBody()) { 417 trace.report(ABSTRACT_PROPERTY_WITH_GETTER.on(getter)); 418 } 419 if (setter != null && setter.hasBody()) { 420 trace.report(ABSTRACT_PROPERTY_WITH_SETTER.on(setter)); 421 } 422 } 423 } 424 425 private void checkPropertyInitializer(@NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { 426 JetPropertyAccessor getter = property.getGetter(); 427 JetPropertyAccessor setter = property.getSetter(); 428 boolean hasAccessorImplementation = (getter != null && getter.hasBody()) || 429 (setter != null && setter.hasBody()); 430 431 if (propertyDescriptor.getModality() == Modality.ABSTRACT) { 432 if (!property.hasDelegateExpressionOrInitializer() && property.getTypeReference() == null) { 433 trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property)); 434 } 435 return; 436 } 437 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 438 boolean inTrait = containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor)containingDeclaration).getKind() == ClassKind.INTERFACE; 439 JetExpression initializer = property.getInitializer(); 440 JetPropertyDelegate delegate = property.getDelegate(); 441 boolean backingFieldRequired = 442 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)); 443 444 if (inTrait && backingFieldRequired && hasAccessorImplementation) { 445 trace.report(BACKING_FIELD_IN_TRAIT.on(property)); 446 } 447 448 if (initializer == null && delegate == null) { 449 boolean error = false; 450 if (backingFieldRequired && !inTrait && !propertyDescriptor.isLateInit() && 451 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.IS_UNINITIALIZED, propertyDescriptor))) { 452 if (!(containingDeclaration instanceof ClassDescriptor) || hasAccessorImplementation) { 453 error = true; 454 trace.report(MUST_BE_INITIALIZED.on(property)); 455 } 456 else { 457 error = true; 458 trace.report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property)); 459 } 460 } 461 if (!error && property.getTypeReference() == null) { 462 trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property)); 463 } 464 if (inTrait && property.hasModifier(JetTokens.FINAL_KEYWORD) && backingFieldRequired) { 465 trace.report(FINAL_PROPERTY_IN_TRAIT.on(property)); 466 } 467 return; 468 } 469 470 if (inTrait) { 471 if (delegate != null) { 472 trace.report(DELEGATED_PROPERTY_IN_TRAIT.on(delegate)); 473 } 474 else { 475 trace.report(PROPERTY_INITIALIZER_IN_TRAIT.on(initializer)); 476 } 477 } 478 else if (delegate == null) { 479 if (!backingFieldRequired) { 480 trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer)); 481 } 482 else if (property.getReceiverTypeReference() != null) { 483 trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer)); 484 } 485 } 486 } 487 488 protected void checkFunction(JetNamedFunction function, SimpleFunctionDescriptor functionDescriptor) { 489 DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration(); 490 boolean hasAbstractModifier = function.hasModifier(JetTokens.ABSTRACT_KEYWORD); 491 if (containingDescriptor instanceof ClassDescriptor) { 492 ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor; 493 boolean inTrait = classDescriptor.getKind() == ClassKind.INTERFACE; 494 if (hasAbstractModifier && !classCanHaveAbstractMembers(classDescriptor)) { 495 trace.report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.getName().asString(), classDescriptor)); 496 } 497 if (hasAbstractModifier && inTrait) { 498 trace.report(ABSTRACT_MODIFIER_IN_TRAIT.on(function)); 499 } 500 boolean hasBody = function.hasBody(); 501 if (hasBody && hasAbstractModifier) { 502 trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor)); 503 } 504 if (!hasBody && function.hasModifier(JetTokens.FINAL_KEYWORD) && inTrait) { 505 trace.report(FINAL_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); 506 } 507 if (!hasBody && !hasAbstractModifier && !inTrait) { 508 trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); 509 } 510 return; 511 } 512 if (!function.hasBody() && !hasAbstractModifier) { 513 trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor)); 514 } 515 } 516 517 private void checkAccessors(@NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { 518 for (JetPropertyAccessor accessor : property.getAccessors()) { 519 PropertyAccessorDescriptor propertyAccessorDescriptor = accessor.isGetter() ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter(); 520 assert propertyAccessorDescriptor != null : "No property accessor descriptor for " + property.getText(); 521 modifiersChecker.checkModifiersForDeclaration(accessor, propertyAccessorDescriptor); 522 } 523 JetPropertyAccessor getter = property.getGetter(); 524 PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter(); 525 JetModifierList getterModifierList = getter != null ? getter.getModifierList() : null; 526 if (getterModifierList != null && getterDescriptor != null) { 527 Map<JetModifierKeywordToken, PsiElement> tokens = modifiersChecker.getTokensCorrespondingToModifiers(getterModifierList, Sets 528 .newHashSet(JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD, 529 JetTokens.INTERNAL_KEYWORD)); 530 if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) { 531 for (PsiElement token : tokens.values()) { 532 trace.report(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.on(token)); 533 } 534 } 535 else { 536 for (PsiElement token : tokens.values()) { 537 trace.report(Errors.REDUNDANT_MODIFIER_IN_GETTER.on(token)); 538 } 539 } 540 } 541 } 542 543 private void checkEnumEntry(@NotNull JetEnumEntry enumEntry, @NotNull ClassDescriptor classDescriptor) { 544 DeclarationDescriptor declaration = classDescriptor.getContainingDeclaration(); 545 if (DescriptorUtils.isEnumClass(declaration)) { 546 ClassDescriptor enumClass = (ClassDescriptor) declaration; 547 548 if (!enumEntry.hasInitializer() && !DescriptorUtils.hasDefaultConstructor(enumClass)) { 549 trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry)); 550 } 551 } 552 else { 553 assert DescriptorUtils.isTrait(declaration) : "Enum entry should be declared in enum class: " + 554 classDescriptor + " " + 555 classDescriptor.getKind(); 556 } 557 } 558 559 }