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