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