001 /* 002 * Copyright 2010-2014 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.jet.lang.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.jet.lang.descriptors.*; 025 import org.jetbrains.jet.lang.diagnostics.Errors; 026 import org.jetbrains.jet.lang.psi.*; 027 import org.jetbrains.jet.lang.types.JetType; 028 import org.jetbrains.jet.lang.types.SubstitutionUtils; 029 import org.jetbrains.jet.lang.types.TypeConstructor; 030 import org.jetbrains.jet.lang.types.TypeProjection; 031 import org.jetbrains.jet.lang.types.checker.JetTypeChecker; 032 import org.jetbrains.jet.lexer.JetModifierKeywordToken; 033 import org.jetbrains.jet.lexer.JetTokens; 034 035 import javax.inject.Inject; 036 import java.util.*; 037 038 import static org.jetbrains.jet.lang.diagnostics.Errors.*; 039 import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE; 040 import static org.jetbrains.jet.lang.resolve.BindingContext.TYPE_PARAMETER; 041 import static org.jetbrains.jet.lang.resolve.DescriptorUtils.classCanHaveAbstractMembers; 042 import static org.jetbrains.jet.lang.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 if (c.getTopDownAnalysisParameters().isLazy()) { 271 checkTypeParameters(aClass); 272 } 273 if (aClass.isTrait()) { 274 checkTraitModifiers(aClass); 275 checkConstructorInTrait(aClass); 276 } 277 else if (aClass.isAnnotation()) { 278 checkAnnotationClassWithBody(aClass); 279 checkValOnAnnotationParameter(aClass); 280 } 281 else if (aClass.isEnum()) { 282 checkEnumModifiers(aClass); 283 if (aClass.isLocal()) { 284 trace.report(LOCAL_ENUM_NOT_ALLOWED.on(aClass, classDescriptor)); 285 } 286 } 287 else if (aClass instanceof JetEnumEntry) { 288 checkEnumEntry((JetEnumEntry) aClass, classDescriptor); 289 } 290 } 291 292 private void checkTypeParameters(JetTypeParameterListOwner typeParameterListOwner) { 293 // TODO: Support annotation for type parameters 294 for (JetTypeParameter jetTypeParameter : typeParameterListOwner.getTypeParameters()) { 295 AnnotationResolver.reportUnsupportedAnnotationForTypeParameter(jetTypeParameter, trace); 296 297 TypeParameterDescriptor typeParameter = trace.get(TYPE_PARAMETER, jetTypeParameter); 298 if (typeParameter != null) { 299 DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter); 300 } 301 } 302 } 303 304 private void checkConstructorInTrait(JetClass klass) { 305 JetParameterList primaryConstructorParameterList = klass.getPrimaryConstructorParameterList(); 306 if (primaryConstructorParameterList != null) { 307 trace.report(CONSTRUCTOR_IN_TRAIT.on(primaryConstructorParameterList)); 308 } 309 } 310 311 private void checkTraitModifiers(JetClass aClass) { 312 reportErrorIfHasIllegalModifier(aClass); 313 JetModifierList modifierList = aClass.getModifierList(); 314 if (modifierList == null) return; 315 if (modifierList.hasModifier(JetTokens.FINAL_KEYWORD)) { 316 trace.report(Errors.TRAIT_CAN_NOT_BE_FINAL.on(aClass)); 317 } 318 if (modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { 319 trace.report(Errors.ABSTRACT_MODIFIER_IN_TRAIT.on(aClass)); 320 } 321 if (modifierList.hasModifier(JetTokens.OPEN_KEYWORD)) { 322 trace.report(Errors.OPEN_MODIFIER_IN_TRAIT.on(aClass)); 323 } 324 } 325 326 private void checkAnnotationClassWithBody(JetClassOrObject classOrObject) { 327 if (classOrObject.getBody() != null) { 328 trace.report(ANNOTATION_CLASS_WITH_BODY.on(classOrObject.getBody())); 329 } 330 } 331 332 private void checkValOnAnnotationParameter(JetClass aClass) { 333 for (JetParameter parameter : aClass.getPrimaryConstructorParameters()) { 334 if (!parameter.hasValOrVarNode()) { 335 trace.report(MISSING_VAL_ON_ANNOTATION_PARAMETER.on(parameter)); 336 } 337 } 338 } 339 340 private void checkOpenMembers(ClassDescriptorWithResolutionScopes classDescriptor) { 341 if (classCanHaveOpenMembers(classDescriptor)) return; 342 343 for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) { 344 if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) continue; 345 JetNamedDeclaration member = (JetNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor); 346 if (member != null && member.hasModifier(JetTokens.OPEN_KEYWORD)) { 347 trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member)); 348 } 349 } 350 } 351 352 private void checkProperty(JetProperty property, PropertyDescriptor propertyDescriptor) { 353 reportErrorIfHasIllegalModifier(property); 354 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 355 if (containingDeclaration instanceof ClassDescriptor) { 356 checkPropertyAbstractness(property, propertyDescriptor, (ClassDescriptor) containingDeclaration); 357 } 358 else { 359 modifiersChecker.checkIllegalModalityModifiers(property); 360 } 361 checkPropertyInitializer(property, propertyDescriptor); 362 checkAccessors(property, propertyDescriptor); 363 checkDeclaredTypeInPublicMember(property, propertyDescriptor); 364 } 365 366 private void checkDeclaredTypeInPublicMember(JetNamedDeclaration member, CallableMemberDescriptor memberDescriptor) { 367 boolean hasDeferredType; 368 if (member instanceof JetProperty) { 369 hasDeferredType = ((JetProperty) member).getTypeReference() == null && DescriptorResolver.hasBody((JetProperty) member); 370 } 371 else { 372 assert member instanceof JetFunction; 373 JetFunction function = (JetFunction) member; 374 hasDeferredType = function.getTypeReference() == null && function.hasBody() && !function.hasBlockBody(); 375 } 376 if ((memberDescriptor.getVisibility().isPublicAPI()) && memberDescriptor.getOverriddenDescriptors().size() == 0 && hasDeferredType) { 377 trace.report(PUBLIC_MEMBER_SHOULD_SPECIFY_TYPE.on(member)); 378 } 379 } 380 381 private void checkPropertyAbstractness( 382 @NotNull JetProperty property, 383 @NotNull PropertyDescriptor propertyDescriptor, 384 @NotNull ClassDescriptor classDescriptor 385 ) { 386 JetPropertyAccessor getter = property.getGetter(); 387 JetPropertyAccessor setter = property.getSetter(); 388 JetModifierList modifierList = property.getModifierList(); 389 ASTNode abstractNode = modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null; 390 391 if (abstractNode != null) { //has abstract modifier 392 if (!classCanHaveAbstractMembers(classDescriptor)) { 393 String name = property.getName(); 394 trace.report(ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(property, name != null ? name : "", classDescriptor)); 395 return; 396 } 397 if (classDescriptor.getKind() == ClassKind.TRAIT) { 398 trace.report(ABSTRACT_MODIFIER_IN_TRAIT.on(property)); 399 } 400 } 401 402 if (propertyDescriptor.getModality() == Modality.ABSTRACT) { 403 JetExpression initializer = property.getInitializer(); 404 if (initializer != null) { 405 trace.report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(initializer)); 406 } 407 JetPropertyDelegate delegate = property.getDelegate(); 408 if (delegate != null) { 409 trace.report(ABSTRACT_DELEGATED_PROPERTY.on(delegate)); 410 } 411 if (getter != null && getter.hasBody()) { 412 trace.report(ABSTRACT_PROPERTY_WITH_GETTER.on(getter)); 413 } 414 if (setter != null && setter.hasBody()) { 415 trace.report(ABSTRACT_PROPERTY_WITH_SETTER.on(setter)); 416 } 417 } 418 } 419 420 private void checkPropertyInitializer(@NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { 421 JetPropertyAccessor getter = property.getGetter(); 422 JetPropertyAccessor setter = property.getSetter(); 423 boolean hasAccessorImplementation = (getter != null && getter.hasBody()) || 424 (setter != null && setter.hasBody()); 425 426 if (propertyDescriptor.getModality() == Modality.ABSTRACT) { 427 if (!property.hasDelegateExpressionOrInitializer() && property.getTypeReference() == null) { 428 trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property)); 429 } 430 return; 431 } 432 DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); 433 boolean inTrait = containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor)containingDeclaration).getKind() == ClassKind.TRAIT; 434 JetExpression initializer = property.getInitializer(); 435 JetPropertyDelegate delegate = property.getDelegate(); 436 boolean backingFieldRequired = 437 Boolean.TRUE.equals(trace.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)); 438 439 if (inTrait && backingFieldRequired && hasAccessorImplementation) { 440 trace.report(BACKING_FIELD_IN_TRAIT.on(property)); 441 } 442 443 if (initializer == null && delegate == null) { 444 boolean error = false; 445 if (backingFieldRequired && !inTrait && 446 Boolean.FALSE.equals(trace.getBindingContext().get(BindingContext.IS_INITIALIZED, propertyDescriptor))) { 447 if (!(containingDeclaration instanceof ClassDescriptor) || hasAccessorImplementation) { 448 error = true; 449 trace.report(MUST_BE_INITIALIZED.on(property)); 450 } 451 else { 452 error = true; 453 trace.report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property)); 454 } 455 } 456 if (!error && property.getTypeReference() == null) { 457 trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property)); 458 } 459 if (inTrait && property.hasModifier(JetTokens.FINAL_KEYWORD) && backingFieldRequired) { 460 trace.report(FINAL_PROPERTY_IN_TRAIT.on(property)); 461 } 462 return; 463 } 464 465 if (inTrait) { 466 if (delegate != null) { 467 trace.report(DELEGATED_PROPERTY_IN_TRAIT.on(delegate)); 468 } 469 else { 470 trace.report(PROPERTY_INITIALIZER_IN_TRAIT.on(initializer)); 471 } 472 } 473 else if (delegate == null) { 474 if (!backingFieldRequired) { 475 trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer)); 476 } 477 else if (property.getReceiverTypeReference() != null) { 478 trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer)); 479 } 480 } 481 } 482 483 protected void checkFunction(JetNamedFunction function, SimpleFunctionDescriptor functionDescriptor) { 484 reportErrorIfHasIllegalModifier(function); 485 DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration(); 486 boolean hasAbstractModifier = function.hasModifier(JetTokens.ABSTRACT_KEYWORD); 487 checkDeclaredTypeInPublicMember(function, functionDescriptor); 488 if (containingDescriptor instanceof ClassDescriptor) { 489 ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor; 490 boolean inTrait = classDescriptor.getKind() == ClassKind.TRAIT; 491 if (hasAbstractModifier && !classCanHaveAbstractMembers(classDescriptor)) { 492 trace.report(ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on(function, functionDescriptor.getName().asString(), classDescriptor)); 493 } 494 if (hasAbstractModifier && inTrait) { 495 trace.report(ABSTRACT_MODIFIER_IN_TRAIT.on(function)); 496 } 497 boolean hasBody = function.hasBody(); 498 if (hasBody && hasAbstractModifier) { 499 trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor)); 500 } 501 if (!hasBody && function.hasModifier(JetTokens.FINAL_KEYWORD) && inTrait) { 502 trace.report(FINAL_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); 503 } 504 if (!hasBody && !hasAbstractModifier && !inTrait) { 505 trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); 506 } 507 return; 508 } 509 modifiersChecker.checkIllegalModalityModifiers(function); 510 if (!function.hasBody() && !hasAbstractModifier) { 511 trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor)); 512 } 513 } 514 515 private void checkAccessors(@NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { 516 for (JetPropertyAccessor accessor : property.getAccessors()) { 517 modifiersChecker.checkIllegalModalityModifiers(accessor); 518 } 519 JetPropertyAccessor getter = property.getGetter(); 520 PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter(); 521 JetModifierList getterModifierList = getter != null ? getter.getModifierList() : null; 522 if (getterModifierList != null && getterDescriptor != null) { 523 Map<JetModifierKeywordToken, ASTNode> nodes = ModifiersChecker.getNodesCorrespondingToModifiers(getterModifierList, Sets 524 .newHashSet(JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD, 525 JetTokens.INTERNAL_KEYWORD)); 526 if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) { 527 for (ASTNode node : nodes.values()) { 528 trace.report(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.on(node.getPsi())); 529 } 530 } 531 else { 532 for (ASTNode node : nodes.values()) { 533 trace.report(Errors.REDUNDANT_MODIFIER_IN_GETTER.on(node.getPsi())); 534 } 535 } 536 } 537 } 538 539 private void checkEnumModifiers(JetClass aClass) { 540 if (aClass.hasModifier(JetTokens.OPEN_KEYWORD)) { 541 trace.report(OPEN_MODIFIER_IN_ENUM.on(aClass)); 542 } 543 if (aClass.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { 544 trace.report(ABSTRACT_MODIFIER_IN_ENUM.on(aClass)); 545 } 546 } 547 548 private void checkEnumEntry(@NotNull JetEnumEntry enumEntry, @NotNull ClassDescriptor classDescriptor) { 549 DeclarationDescriptor declaration = classDescriptor.getContainingDeclaration(); 550 assert DescriptorUtils.isEnumClass(declaration) : "Enum entry should be declared in enum class: " + classDescriptor; 551 ClassDescriptor enumClass = (ClassDescriptor) declaration; 552 553 List<JetDelegationSpecifier> delegationSpecifiers = enumEntry.getDelegationSpecifiers(); 554 ConstructorDescriptor constructor = enumClass.getUnsubstitutedPrimaryConstructor(); 555 assert constructor != null; 556 if (!constructor.getValueParameters().isEmpty() && delegationSpecifiers.isEmpty()) { 557 trace.report(ENUM_ENTRY_SHOULD_BE_INITIALIZED.on(enumEntry, enumClass)); 558 } 559 560 for (JetDelegationSpecifier delegationSpecifier : delegationSpecifiers) { 561 JetTypeReference typeReference = delegationSpecifier.getTypeReference(); 562 if (typeReference != null) { 563 JetType type = trace.getBindingContext().get(TYPE, typeReference); 564 if (type != null) { 565 JetType enumType = enumClass.getDefaultType(); 566 if (!type.getConstructor().equals(enumType.getConstructor())) { 567 trace.report(ENUM_ENTRY_ILLEGAL_TYPE.on(typeReference, enumClass)); 568 } 569 } 570 } 571 } 572 } 573 }