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