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