private void checkAccessors( @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { for (JetPropertyAccessor accessor : property.getAccessors()) { PropertyAccessorDescriptor propertyAccessorDescriptor = accessor.isGetter() ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter(); assert propertyAccessorDescriptor != null : "No property accessor descriptor for " + property.getText(); modifiersChecker.checkModifiersForDeclaration(accessor, propertyAccessorDescriptor); modifiersChecker.reportIllegalModalityModifiers(accessor); } JetPropertyAccessor getter = property.getGetter(); PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter(); JetModifierList getterModifierList = getter != null ? getter.getModifierList() : null; if (getterModifierList != null && getterDescriptor != null) { Map<JetModifierKeywordToken, ASTNode> nodes = ModifiersChecker.getNodesCorrespondingToModifiers( getterModifierList, Sets.newHashSet( JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD, JetTokens.INTERNAL_KEYWORD)); if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) { for (ASTNode node : nodes.values()) { trace.report(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.on(node.getPsi())); } } else { for (ASTNode node : nodes.values()) { trace.report(Errors.REDUNDANT_MODIFIER_IN_GETTER.on(node.getPsi())); } } } }
@NotNull private Collection<PsiElement> getDeclarationsByDescriptor( @NotNull DeclarationDescriptor declarationDescriptor) { Collection<PsiElement> declarations; if (declarationDescriptor instanceof PackageViewDescriptor) { final PackageViewDescriptor aPackage = (PackageViewDescriptor) declarationDescriptor; Collection<JetFile> files = trace.get(BindingContext.PACKAGE_TO_FILES, aPackage.getFqName()); if (files == null) { return Collections .emptyList(); // package can be defined out of Kotlin sources, e. g. in library or Java // code } declarations = Collections2.transform( files, new Function<JetFile, PsiElement>() { @Override public PsiElement apply(@Nullable JetFile file) { assert file != null : "File is null for aPackage " + aPackage; return file.getPackageDirective().getNameIdentifier(); } }); } else { declarations = Collections.singletonList( BindingContextUtils.descriptorToDeclaration( trace.getBindingContext(), declarationDescriptor)); } return declarations; }
public static void reportCyclicInheritanceHierarchyError( @NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor, @NotNull ClassDescriptor superclass) { PsiElement psiElement = BindingContextUtils.classDescriptorToDeclaration( trace.getBindingContext(), classDescriptor); PsiElement elementToMark = null; if (psiElement instanceof JetClassOrObject) { JetClassOrObject classOrObject = (JetClassOrObject) psiElement; for (JetDelegationSpecifier delegationSpecifier : classOrObject.getDelegationSpecifiers()) { JetTypeReference typeReference = delegationSpecifier.getTypeReference(); if (typeReference == null) continue; JetType supertype = trace.get(TYPE, typeReference); if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) { elementToMark = typeReference; } } } if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) { PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement; PsiElement nameIdentifier = namedElement.getNameIdentifier(); if (nameIdentifier != null) { elementToMark = nameIdentifier; } } if (elementToMark != null) { trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark)); } }
private void reportCyclicInheritanceHierarchyError( @NotNull BindingTrace trace, @NotNull ClassDescriptor classDescriptor, @NotNull ClassDescriptor superclass) { PsiElement psiElement = DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor); PsiElement elementToMark = null; if (psiElement instanceof KtClassOrObject) { KtClassOrObject classOrObject = (KtClassOrObject) psiElement; for (KtSuperTypeListEntry delegationSpecifier : classOrObject.getSuperTypeListEntries()) { KtTypeReference typeReference = delegationSpecifier.getTypeReference(); if (typeReference == null) continue; KotlinType supertype = trace.get(TYPE, typeReference); if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) { elementToMark = typeReference; } } } if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) { PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement; PsiElement nameIdentifier = namedElement.getNameIdentifier(); if (nameIdentifier != null) { elementToMark = nameIdentifier; } } if (elementToMark != null) { trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark)); } }
private void checkClass( BodiesResolveContext c, JetClass aClass, ClassDescriptorWithResolutionScopes classDescriptor) { checkOpenMembers(classDescriptor); checkTypeParameters(aClass); if (aClass.isInterface()) { ASTNode traitKeyword = aClass.getNode().findChildByType(JetTokens.TRAIT_KEYWORD); if (traitKeyword != null) { trace.report(Errors.DEPRECATED_TRAIT_KEYWORD.on(traitKeyword.getPsi())); } checkTraitModifiers(aClass); checkConstructorInTrait(aClass); } else if (aClass.isAnnotation()) { checkAnnotationClassWithBody(aClass); checkValOnAnnotationParameter(aClass); } else if (aClass.isEnum()) { checkEnumModifiers(aClass); if (aClass.isLocal()) { trace.report(LOCAL_ENUM_NOT_ALLOWED.on(aClass, classDescriptor)); } } else if (aClass.hasModifier(JetTokens.SEALED_KEYWORD)) { checkSealedModifiers(aClass); } else if (aClass instanceof JetEnumEntry) { checkEnumEntry((JetEnumEntry) aClass, classDescriptor); } }
@NotNull public static JetExpression createStubExpressionOfNecessaryType( @NotNull Project project, @NotNull JetType type, @NotNull BindingTrace trace) { JetExpression expression = JetPsiFactory.createExpression(project, "$e"); trace.record(PROCESSED, expression); trace.record(EXPRESSION_TYPE, expression, type); return expression; }
private void checkEnumModifiers(JetClass aClass) { if (aClass.hasModifier(JetTokens.OPEN_KEYWORD)) { trace.report(OPEN_MODIFIER_IN_ENUM.on(aClass)); } if (aClass.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { trace.report(ABSTRACT_MODIFIER_IN_ENUM.on(aClass)); } if (aClass.hasModifier(JetTokens.SEALED_KEYWORD)) { trace.report(SEALED_MODIFIER_IN_ENUM.on(aClass)); } }
private void checkSealedModifiers(JetClass aClass) { if (aClass.hasModifier(JetTokens.OPEN_KEYWORD)) { trace.report(OPEN_MODIFIER_IN_SEALED.on(aClass)); } if (aClass.hasModifier(JetTokens.FINAL_KEYWORD)) { trace.report(FINAL_MODIFIER_IN_SEALED.on(aClass)); } if (aClass.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { trace.report(ABSTRACT_MODIFIER_IN_SEALED.on(aClass)); } }
public static void reportAmbiguousLabel( @NotNull BindingTrace trace, @NotNull JetSimpleNameExpression targetLabel, @NotNull Collection<DeclarationDescriptor> declarationsByLabel) { Collection<PsiElement> targets = Lists.newArrayList(); for (DeclarationDescriptor descriptor : declarationsByLabel) { PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(descriptor); assert element != null : "Label can only point to something in the same lexical scope"; targets.add(element); } if (!targets.isEmpty()) { trace.record(AMBIGUOUS_LABEL_TARGET, targetLabel, targets); } trace.report(AMBIGUOUS_LABEL.on(targetLabel)); }
@NotNull public Collection<? extends DeclarationDescriptor> lookupDescriptorsForUserType( @NotNull JetUserType userType, @NotNull JetScope outerScope, @NotNull BindingTrace trace) { if (userType.isAbsoluteInRootNamespace()) { trace.report(Errors.UNSUPPORTED.on(userType, "package")); return Collections.emptyList(); } JetSimpleNameExpression referenceExpression = userType.getReferenceExpression(); if (referenceExpression == null) { return Collections.emptyList(); } JetUserType qualifier = userType.getQualifier(); if (qualifier == null) { return lookupDescriptorsForSimpleNameReference( referenceExpression, outerScope, outerScope, trace, LookupMode.ONLY_CLASSES, false, true); } Collection<? extends DeclarationDescriptor> declarationDescriptors = lookupDescriptorsForUserType(qualifier, outerScope, trace); return lookupSelectorDescriptors( referenceExpression, declarationDescriptors, trace, outerScope, LookupMode.ONLY_CLASSES, true); }
static void addOwnDataTo( @NotNull final BindingTrace trace, @Nullable final TraceEntryFilter filter, boolean commitDiagnostics, @NotNull MutableSlicedMap map, MutableDiagnosticsWithSuppression diagnostics) { map.forEach( new Function3<WritableSlice, Object, Object, Void>() { @Override public Void invoke(WritableSlice slice, Object key, Object value) { if (filter == null || filter.accept(slice, key)) { trace.record(slice, key, value); } return null; } }); if (!commitDiagnostics) return; for (Diagnostic diagnostic : diagnostics.getOwnDiagnostics()) { if (filter == null || filter.accept(null, diagnostic.getPsiElement())) { trace.report(diagnostic); } } }
public static AnalyzeExhaust analyzeFilesWithJavaIntegration( Project project, Collection<JetFile> files, BindingTrace trace, List<AnalyzerScriptParameter> scriptParameters, Predicate<PsiFile> filesToAnalyzeCompletely, boolean storeContextForBodiesResolve) { final ModuleDescriptor owner = new ModuleDescriptor(Name.special("<module>")); TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(filesToAnalyzeCompletely, false, false, scriptParameters); InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm( project, topDownAnalysisParameters, new ObservableBindingTrace(trace), owner); try { injector.getTopDownAnalyzer().analyzeFiles(files, scriptParameters); BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ? new CachedBodiesResolveContext(injector.getTopDownAnalysisContext()) : null; return AnalyzeExhaust.success( trace.getBindingContext(), bodiesResolveContext, injector.getModuleConfiguration()); } finally { injector.destroy(); } }
/** * This method tries to resolve descriptors ambiguity between class descriptor and package * descriptor for the same class. It's ok choose class for expression reference resolution. * * @return <code>true</code> if method has successfully resolved ambiguity */ private static boolean resolveClassPackageAmbiguity( @NotNull Collection<DeclarationDescriptor> filteredDescriptors, @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope resolutionScope, @NotNull BindingTrace trace, @NotNull JetScope scopeToCheckVisibility) { if (filteredDescriptors.size() == 2) { PackageViewDescriptor packageView = null; ClassDescriptor classDescriptor = null; for (DeclarationDescriptor filteredDescriptor : filteredDescriptors) { if (filteredDescriptor instanceof PackageViewDescriptor) { packageView = (PackageViewDescriptor) filteredDescriptor; } else if (filteredDescriptor instanceof ClassDescriptor) { classDescriptor = (ClassDescriptor) filteredDescriptor; } } if (packageView != null && classDescriptor != null) { if (packageView.getFqName().equalsTo(DescriptorUtils.getFqName(classDescriptor))) { trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, classDescriptor); trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); checkVisibility(classDescriptor, trace, referenceExpression, scopeToCheckVisibility); return true; } } } return false; }
private void checkValOnAnnotationParameter(JetClass aClass) { for (JetParameter parameter : aClass.getPrimaryConstructorParameters()) { if (!parameter.hasValOrVar()) { trace.report(MISSING_VAL_ON_ANNOTATION_PARAMETER.on(parameter)); } } }
private void checkTraitModifiers(JetClass aClass) { reportErrorIfHasIllegalModifier(aClass); JetModifierList modifierList = aClass.getModifierList(); if (modifierList == null) return; if (modifierList.hasModifier(JetTokens.FINAL_KEYWORD)) { trace.report(Errors.TRAIT_CAN_NOT_BE_FINAL.on(aClass)); } if (modifierList.hasModifier(JetTokens.SEALED_KEYWORD)) { trace.report(Errors.TRAIT_CAN_NOT_BE_SEALED.on(aClass)); } if (modifierList.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { trace.report(Errors.ABSTRACT_MODIFIER_IN_TRAIT.on(aClass)); } if (modifierList.hasModifier(JetTokens.OPEN_KEYWORD)) { trace.report(Errors.OPEN_MODIFIER_IN_TRAIT.on(aClass)); } }
private void checkFinalUpperBounds(@Nullable JetTypeReference typeReference) { if (typeReference != null) { JetType type = trace.getBindingContext().get(TYPE, typeReference); if (type != null) { DescriptorResolver.checkUpperBoundType(typeReference, type, trace); } } }
private void checkBoundsForTypeInClassHeader(@Nullable JetTypeReference typeReference) { if (typeReference != null) { JetType type = trace.getBindingContext().get(TYPE, typeReference); if (type != null) { DescriptorResolver.checkBounds(typeReference, type, trace); } } }
private static void recordConstructorDelegationCall( @NotNull BindingTrace trace, @NotNull ConstructorDescriptor constructor, @NotNull ResolvedCall<?> call) { //noinspection unchecked trace.record( CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor, (ResolvedCall<ConstructorDescriptor>) call); }
public void checkParameterHasNoValOrVar( @NotNull JetParameter parameter, @NotNull DiagnosticFactory1<PsiElement, JetKeywordToken> diagnosticFactory) { PsiElement valOrVar = parameter.getValOrVarKeyword(); if (valOrVar != null) { trace.report( diagnosticFactory.on( valOrVar, ((JetKeywordToken) valOrVar.getNode().getElementType()))); } }
public static void recordFunctionDeclarationToDescriptor( @NotNull BindingTrace trace, @NotNull PsiElement psiElement, @NotNull SimpleFunctionDescriptor function) { if (function.getKind() != DECLARATION) { throw new IllegalArgumentException( "function of kind " + function.getKind() + " cannot have declaration"); } trace.record(BindingContext.FUNCTION, psiElement, function); }
private void checkOpenMembers(ClassDescriptorWithResolutionScopes classDescriptor) { if (classCanHaveOpenMembers(classDescriptor)) return; for (CallableMemberDescriptor memberDescriptor : classDescriptor.getDeclaredCallableMembers()) { if (memberDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) continue; JetNamedDeclaration member = (JetNamedDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(memberDescriptor); if (member != null && member.hasModifier(JetTokens.OPEN_KEYWORD)) { trace.report(NON_FINAL_MEMBER_IN_FINAL_CLASS.on(member)); } } }
private void checkTypeParameters(JetTypeParameterListOwner typeParameterListOwner) { // TODO: Support annotation for type parameters for (JetTypeParameter jetTypeParameter : typeParameterListOwner.getTypeParameters()) { AnnotationResolver.reportUnsupportedAnnotationForTypeParameter(jetTypeParameter, trace); TypeParameterDescriptor typeParameter = trace.get(TYPE_PARAMETER, jetTypeParameter); if (typeParameter != null) { DescriptorResolver.checkConflictingUpperBounds(trace, typeParameter, jetTypeParameter); } AnnotationTargetChecker.INSTANCE$.check(jetTypeParameter, trace); } }
private void checkNestedClassAllowed( @NotNull JetModifierListOwner modifierListOwner, @NotNull DeclarationDescriptor descriptor) { if (modifierListOwner.hasModifier(INNER_KEYWORD)) return; if (modifierListOwner instanceof JetClass && !(modifierListOwner instanceof JetEnumEntry)) { JetClass aClass = (JetClass) modifierListOwner; boolean localEnumError = aClass.isLocal() && aClass.isEnum(); if (!localEnumError && isIllegalNestedClass(descriptor)) { trace.report(NESTED_CLASS_NOT_ALLOWED.on(aClass)); } } }
protected void checkFunction( JetNamedFunction function, SimpleFunctionDescriptor functionDescriptor) { reportErrorIfHasIllegalModifier(function); DeclarationDescriptor containingDescriptor = functionDescriptor.getContainingDeclaration(); boolean hasAbstractModifier = function.hasModifier(JetTokens.ABSTRACT_KEYWORD); checkDeclaredTypeInPublicMember(function, functionDescriptor); if (containingDescriptor instanceof ClassDescriptor) { ClassDescriptor classDescriptor = (ClassDescriptor) containingDescriptor; boolean inTrait = classDescriptor.getKind() == ClassKind.INTERFACE; if (hasAbstractModifier && !classCanHaveAbstractMembers(classDescriptor)) { trace.report( ABSTRACT_FUNCTION_IN_NON_ABSTRACT_CLASS.on( function, functionDescriptor.getName().asString(), classDescriptor)); } if (hasAbstractModifier && inTrait) { trace.report(ABSTRACT_MODIFIER_IN_TRAIT.on(function)); } boolean hasBody = function.hasBody(); if (hasBody && hasAbstractModifier) { trace.report(ABSTRACT_FUNCTION_WITH_BODY.on(function, functionDescriptor)); } if (!hasBody && function.hasModifier(JetTokens.FINAL_KEYWORD) && inTrait) { trace.report(FINAL_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); } if (!hasBody && !hasAbstractModifier && !inTrait) { trace.report(NON_ABSTRACT_FUNCTION_WITH_NO_BODY.on(function, functionDescriptor)); } return; } modifiersChecker.reportIllegalModalityModifiers(function); if (!function.hasBody() && !hasAbstractModifier) { trace.report(NON_MEMBER_FUNCTION_NO_BODY.on(function, functionDescriptor)); } }
@Nullable public static JetType updateRecordedType( @Nullable JetType type, @NotNull JetExpression expression, @NotNull BindingTrace trace, boolean shouldBeMadeNullable) { if (type == null) return null; if (shouldBeMadeNullable) { type = TypeUtils.makeNullable(type); } trace.record(BindingContext.EXPRESSION_TYPE, expression, type); return type; }
private static boolean canImportMembersFrom( @NotNull DeclarationDescriptor descriptor, @NotNull JetSimpleNameExpression reference, @NotNull BindingTrace trace, @NotNull LookupMode lookupMode) { assert lookupMode == LookupMode.EVERYTHING; if (descriptor instanceof PackageViewDescriptor) { return true; } if (descriptor instanceof ClassDescriptor) { return true; } trace.report(CANNOT_IMPORT_FROM_ELEMENT.on(reference, descriptor)); return false; }
private void reportRedeclarations(@NotNull Multimap<Name, DeclarationDescriptor> descriptorMap) { Set<Pair<PsiElement, Name>> redeclarations = Sets.newHashSet(); for (Name name : descriptorMap.keySet()) { Collection<DeclarationDescriptor> descriptors = descriptorMap.get(name); if (descriptors.size() > 1) { // We mustn't compare PropertyDescriptor with PropertyDescriptor because we do this at // OverloadResolver for (DeclarationDescriptor descriptor : descriptors) { if (descriptor instanceof ClassDescriptor) { for (DeclarationDescriptor descriptor2 : descriptors) { if (descriptor == descriptor2) { continue; } redeclarations.add( Pair.create( BindingContextUtils.classDescriptorToDeclaration( trace.getBindingContext(), (ClassDescriptor) descriptor), descriptor.getName())); if (descriptor2 instanceof PropertyDescriptor) { redeclarations.add( Pair.create( BindingContextUtils.descriptorToDeclaration( trace.getBindingContext(), descriptor2), descriptor2.getName())); } } } } } } for (Pair<PsiElement, Name> redeclaration : redeclarations) { trace.report( REDECLARATION.on(redeclaration.getFirst(), redeclaration.getSecond().asString())); } }
private void checkVisibility( @NotNull DeclarationDescriptorWithVisibility descriptor, @NotNull BindingTrace trace, @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope scopeToCheckVisibility) { if (!Visibilities.isVisible(descriptor, scopeToCheckVisibility.getContainingDeclaration())) { trace.report( INVISIBLE_REFERENCE.on( referenceExpression, descriptor, descriptor.getVisibility(), descriptor.getContainingDeclaration())); } }
private void checkPrimaryConstructor( JetClassOrObject classOrObject, ClassDescriptor classDescriptor) { ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); JetPrimaryConstructor declaration = classOrObject.getPrimaryConstructor(); if (primaryConstructor == null || declaration == null) return; for (JetParameter parameter : declaration.getValueParameters()) { PropertyDescriptor propertyDescriptor = trace.get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); if (propertyDescriptor != null) { modifiersChecker.checkModifiersForDeclaration(parameter, propertyDescriptor); } } if (declaration.getModifierList() != null && !declaration.hasConstructorKeyword()) { trace.report(MISSING_CONSTRUCTOR_KEYWORD.on(declaration.getModifierList())); } if (!(classOrObject instanceof JetClass)) { trace.report(CONSTRUCTOR_IN_OBJECT.on(declaration)); } checkConstructorDeclaration(primaryConstructor, declaration); }
private static void checkVisibility( @NotNull DeclarationDescriptorWithVisibility descriptor, @NotNull BindingTrace trace, @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope scopeToCheckVisibility) { if (!Visibilities.isVisible( ReceiverValue.IRRELEVANT_RECEIVER, descriptor, scopeToCheckVisibility.getContainingDeclaration())) { Visibility visibility = descriptor.getVisibility(); if (PsiTreeUtil.getParentOfType(referenceExpression, JetImportDirective.class) != null && !visibility.mustCheckInImports()) return; //noinspection ConstantConditions trace.report( INVISIBLE_REFERENCE.on( referenceExpression, descriptor, visibility, descriptor.getContainingDeclaration())); } }