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