FIR: allow diagnostic collection on default property accessors

This commit is contained in:
Mikhail Glukhikh
2021-10-06 16:00:35 +03:00
committed by teamcityserver
parent 39fe457f91
commit 2a9a1dbb86
15 changed files with 37 additions and 142 deletions
@@ -5,12 +5,12 @@ abstract class A {
class C1 : A() {
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> override var attribute = super.attribute
public set
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> set
}
abstract class B2 : A() {
override var attribute = "b"
public set
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> set
}
class C2 : B2() {
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
object FirJvmExternalDeclarationChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration is FirPropertyAccessor) return
checkInternal(declaration, null, null, context, reporter)
}
@@ -120,18 +120,20 @@ object FirExposedVisibilityDeclarationChecker : FirBasicDeclarationChecker() {
)
}
}
declaration.valueParameters.forEachIndexed { i, valueParameter ->
if (i < declaration.valueParameters.size) {
val (restricting, restrictingVisibility) = valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()
?.findVisibilityExposure(context, functionVisibility) ?: return@forEachIndexed
reporter.reportOn(
valueParameter.source,
FirErrors.EXPOSED_PARAMETER_TYPE,
functionVisibility,
restricting,
restrictingVisibility,
context
)
if (declaration !is FirPropertyAccessor) {
declaration.valueParameters.forEachIndexed { i, valueParameter ->
if (i < declaration.valueParameters.size) {
val (restricting, restrictingVisibility) = valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()
?.findVisibilityExposure(context, functionVisibility) ?: return@forEachIndexed
reporter.reportOn(
valueParameter.source,
FirErrors.EXPOSED_PARAMETER_TYPE,
functionVisibility,
restricting,
restrictingVisibility,
context
)
}
}
}
checkMemberReceiver(declaration.receiverTypeRef, declaration as? FirCallableDeclaration, reporter, context)
@@ -18,7 +18,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.hasBody
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
@@ -34,17 +33,6 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
val source = declaration.source ?: return
if (source.kind is FirFakeSourceElementKind) return
if (declaration is FirProperty) {
fun checkPropertyAccessor(propertyAccessor: FirPropertyAccessor?) {
if (propertyAccessor != null && !propertyAccessor.hasBody) {
check(propertyAccessor, context, reporter)
}
}
checkPropertyAccessor(declaration.getter)
checkPropertyAccessor(declaration.setter)
}
source.getModifierList()?.let { checkModifiers(it, declaration, context, reporter) }
}
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange
import org.jetbrains.kotlin.fir.FirFakeSourceElement
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
import org.jetbrains.kotlin.fir.analysis.cfa.util.PathAwarePropertyInitializationInfo
@@ -40,7 +40,7 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
for (property in unprocessedProperties) {
val source = property.source
if (source is FirFakeSourceElement) continue
if (source?.kind is FirFakeSourceElementKind) continue
if (source?.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION) continue
propertiesCharacteristics[property] = EventOccurrencesRange.ZERO
}
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.checkers.extended
import org.jetbrains.kotlin.fir.FirFakeSourceElement
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
object EmptyRangeChecker : FirFunctionCallChecker() {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) {
if (expression.source is FirFakeSourceElement) return
if (expression.source?.kind is FirFakeSourceElementKind) return
val left = expression.rangeLeft ?: return
val right = expression.rangeRight ?: return
@@ -7,12 +7,10 @@ package org.jetbrains.kotlin.fir.analysis.checkers.extended
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirFakeSourceElement
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isLocalMember
import org.jetbrains.kotlin.fir.analysis.checkers.findClosestClassOrObject
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.analysis.checkers.overriddenFunctions
@@ -42,7 +40,7 @@ object RedundantVisibilityModifierSyntaxChecker : FirDeclarationSyntaxChecker<Fi
reporter: DiagnosticReporter
) {
if (element is FirConstructor && source.kind is FirFakeSourceElementKind) return
if (source is FirFakeSourceElement) return
if (source.kind is FirFakeSourceElementKind) return
if (
element !is FirMemberDeclaration
&& !(element is FirPropertyAccessor && element.visibility == context.containingPropertyVisibility)
@@ -127,11 +127,9 @@ abstract class AbstractDiagnosticCollectorVisitor(
}
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Nothing?) {
if (propertyAccessor !is FirDefaultPropertyAccessor) {
val property = context.containingDeclarations.last() as FirProperty
withAnnotationContainer(propertyAccessor) {
visitWithDeclarationAndReceiver(propertyAccessor, property.name, property.receiverTypeRef)
}
val property = context.containingDeclarations.last() as FirProperty
withAnnotationContainer(propertyAccessor) {
visitWithDeclarationAndReceiver(propertyAccessor, property.name, property.receiverTypeRef)
}
}
@@ -1142,7 +1142,12 @@ class DeclarationsConverter(
}
this.getter = convertedAccessors.find { it.isGetter }
?: FirDefaultPropertyGetter(
property.toFirSourceElement(FirFakeSourceElementKind.DefaultAccessor), moduleData, FirDeclarationOrigin.Source, returnType, propertyVisibility, symbol,
property.toFirSourceElement(FirFakeSourceElementKind.DefaultAccessor),
moduleData,
FirDeclarationOrigin.Source,
returnType.copyWithNewSourceKind(FirFakeSourceElementKind.DefaultAccessor),
propertyVisibility,
symbol,
).also {
it.status = defaultAccessorStatus()
it.initContainingClassAttr()
@@ -1154,7 +1159,7 @@ class DeclarationsConverter(
property.toFirSourceElement(FirFakeSourceElementKind.DefaultAccessor),
moduleData,
FirDeclarationOrigin.Source,
returnType,
returnType.copyWithNewSourceKind(FirFakeSourceElementKind.DefaultAccessor),
propertyVisibility, symbol,
).also {
it.status = defaultAccessorStatus()
@@ -314,6 +314,7 @@ class FirFakeSourceElement(psi: PsiElement, override val kind: FirFakeSourceElem
}
fun FirSourceElement.fakeElement(newKind: FirFakeSourceElementKind): FirSourceElement {
if (kind == newKind) return this
return when (this) {
is FirLightSourceElement -> FirLightSourceElement(lighterASTNode, startOffset, endOffset, treeStructure, newKind)
is FirPsiSourceElement -> FirFakeSourceElement(psi, newKind)
@@ -8,9 +8,7 @@ package org.jetbrains.kotlin.fir.declarations.impl
import org.jetbrains.kotlin.descriptors.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirImplementationDetail
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildDefaultSetterValueParameter
@@ -126,7 +124,7 @@ class FirDefaultPropertySetter(
FirImplicitUnitTypeRef(source),
valueParameters = mutableListOf(
buildDefaultSetterValueParameter builder@{
this@builder.source = source
this@builder.source = source?.fakeElement(FirFakeSourceElementKind.DefaultAccessor)
this@builder.moduleData = moduleData
this@builder.origin = origin
this@builder.returnTypeRef = propertyTypeRef
@@ -1,16 +0,0 @@
@Target(AnnotationTarget.PROPERTY_GETTER)
annotation class smartget
@Target(AnnotationTarget.PROPERTY_SETTER)
annotation class smartset
@Target(AnnotationTarget.FUNCTION)
annotation class base
class My(x: Int) {
<!WRONG_ANNOTATION_TARGET!>@smartget<!> var y = x
@base @smartget @smartset get
@base @smartget @smartset set
@base <!WRONG_ANNOTATION_TARGET!>@smartget<!> <!WRONG_ANNOTATION_TARGET!>@smartset<!> fun foo() = y
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
@Target(AnnotationTarget.PROPERTY_GETTER)
annotation class smartget
@@ -1,82 +0,0 @@
// FILE: test/AnnotationTargets.java
package test;
import java.lang.annotation.*;
public class AnnotationTargets {
public @interface base {
}
@Target(ElementType.ANNOTATION_TYPE)
public @interface meta {
}
@Target(ElementType.CONSTRUCTOR)
public @interface konstructor {
}
@Target(ElementType.FIELD)
public @interface fieldann {
}
@Target(ElementType.LOCAL_VARIABLE)
public @interface local {
}
@Target(ElementType.METHOD)
public @interface method {
}
@Target(ElementType.PARAMETER)
public @interface parameter {
}
@Target(ElementType.TYPE)
public @interface type {
}
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
public @interface multiple {
}
}
// FILE: test/AnnotationTargets.kt
@file:AnnotationTargets.type
package test
import test.AnnotationTargets.*
@base @meta @type <!WRONG_ANNOTATION_TARGET!>@konstructor<!> annotation class KMeta
@base <!WRONG_ANNOTATION_TARGET!>@meta<!> @type <!WRONG_ANNOTATION_TARGET!>@method<!> <!WRONG_ANNOTATION_TARGET!>@multiple<!> class KClass(
@base @fieldann @parameter val y:
<!WRONG_ANNOTATION_TARGET!>@base<!> <!WRONG_ANNOTATION_TARGET!>@type<!> Int) {
@base @multiple @fieldann <!WRONG_ANNOTATION_TARGET!>@local<!> val x = 0
@method @konstructor @type get
@base @method @multiple <!WRONG_ANNOTATION_TARGET!>@konstructor<!>
fun foo(@parameter <!WRONG_ANNOTATION_TARGET!>@type<!> i:
<!WRONG_ANNOTATION_TARGET!>@base<!> <!WRONG_ANNOTATION_TARGET!>@multiple<!> Int
): <!WRONG_ANNOTATION_TARGET!>@fieldann<!> <!WRONG_ANNOTATION_TARGET!>@parameter<!> Int {
@local @base <!WRONG_ANNOTATION_TARGET!>@multiple<!> <!WRONG_ANNOTATION_TARGET!>@fieldann<!> val j = i + 1
<!WRONG_ANNOTATION_TARGET!>@base<!> <!WRONG_ANNOTATION_TARGET!>@multiple<!> return j
}
@base <!WRONG_ANNOTATION_TARGET!>@method<!> @konstructor constructor(): this(0)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: test/AnnotationTargets.java
package test;