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() { class C1 : A() {
<!REDUNDANT_VISIBILITY_MODIFIER!>public<!> override var attribute = super.attribute <!REDUNDANT_VISIBILITY_MODIFIER!>public<!> override var attribute = super.attribute
public set <!REDUNDANT_VISIBILITY_MODIFIER!>public<!> set
} }
abstract class B2 : A() { abstract class B2 : A() {
override var attribute = "b" override var attribute = "b"
public set <!REDUNDANT_VISIBILITY_MODIFIER!>public<!> set
} }
class C2 : B2() { class C2 : B2() {
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
object FirJvmExternalDeclarationChecker : FirBasicDeclarationChecker() { object FirJvmExternalDeclarationChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration is FirPropertyAccessor) return
checkInternal(declaration, null, null, context, reporter) checkInternal(declaration, null, null, context, reporter)
} }
@@ -120,18 +120,20 @@ object FirExposedVisibilityDeclarationChecker : FirBasicDeclarationChecker() {
) )
} }
} }
declaration.valueParameters.forEachIndexed { i, valueParameter -> if (declaration !is FirPropertyAccessor) {
if (i < declaration.valueParameters.size) { declaration.valueParameters.forEachIndexed { i, valueParameter ->
val (restricting, restrictingVisibility) = valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>() if (i < declaration.valueParameters.size) {
?.findVisibilityExposure(context, functionVisibility) ?: return@forEachIndexed val (restricting, restrictingVisibility) = valueParameter.returnTypeRef.coneTypeSafe<ConeKotlinType>()
reporter.reportOn( ?.findVisibilityExposure(context, functionVisibility) ?: return@forEachIndexed
valueParameter.source, reporter.reportOn(
FirErrors.EXPOSED_PARAMETER_TYPE, valueParameter.source,
functionVisibility, FirErrors.EXPOSED_PARAMETER_TYPE,
restricting, functionVisibility,
restrictingVisibility, restricting,
context restrictingVisibility,
) context
)
}
} }
} }
checkMemberReceiver(declaration.receiverTypeRef, declaration as? FirCallableDeclaration, reporter, 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.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor 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.isCompanion
import org.jetbrains.kotlin.fir.declarations.utils.isInner import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.isLocal
@@ -34,17 +33,6 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
val source = declaration.source ?: return val source = declaration.source ?: return
if (source.kind is FirFakeSourceElementKind) 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) } 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.KtNodeTypes
import org.jetbrains.kotlin.contracts.description.EventOccurrencesRange 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.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker import org.jetbrains.kotlin.fir.analysis.cfa.AbstractFirPropertyInitializationChecker
import org.jetbrains.kotlin.fir.analysis.cfa.util.PathAwarePropertyInitializationInfo import org.jetbrains.kotlin.fir.analysis.cfa.util.PathAwarePropertyInitializationInfo
@@ -40,7 +40,7 @@ object CanBeValChecker : AbstractFirPropertyInitializationChecker() {
for (property in unprocessedProperties) { for (property in unprocessedProperties) {
val source = property.source val source = property.source
if (source is FirFakeSourceElement) continue if (source?.kind is FirFakeSourceElementKind) continue
if (source?.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION) continue if (source?.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION) continue
propertiesCharacteristics[property] = EventOccurrencesRange.ZERO propertiesCharacteristics[property] = EventOccurrencesRange.ZERO
} }
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.checkers.extended 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.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
@@ -17,7 +17,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall
object EmptyRangeChecker : FirFunctionCallChecker() { object EmptyRangeChecker : FirFunctionCallChecker() {
override fun check(expression: FirFunctionCall, context: CheckerContext, reporter: DiagnosticReporter) { 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 left = expression.rangeLeft ?: return
val right = expression.rangeRight ?: 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.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirFakeSourceElement
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext 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.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.findClosestClassOrObject
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.analysis.checkers.overriddenFunctions import org.jetbrains.kotlin.fir.analysis.checkers.overriddenFunctions
@@ -42,7 +40,7 @@ object RedundantVisibilityModifierSyntaxChecker : FirDeclarationSyntaxChecker<Fi
reporter: DiagnosticReporter reporter: DiagnosticReporter
) { ) {
if (element is FirConstructor && source.kind is FirFakeSourceElementKind) return if (element is FirConstructor && source.kind is FirFakeSourceElementKind) return
if (source is FirFakeSourceElement) return if (source.kind is FirFakeSourceElementKind) return
if ( if (
element !is FirMemberDeclaration element !is FirMemberDeclaration
&& !(element is FirPropertyAccessor && element.visibility == context.containingPropertyVisibility) && !(element is FirPropertyAccessor && element.visibility == context.containingPropertyVisibility)
@@ -127,11 +127,9 @@ abstract class AbstractDiagnosticCollectorVisitor(
} }
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Nothing?) { override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor, data: Nothing?) {
if (propertyAccessor !is FirDefaultPropertyAccessor) { val property = context.containingDeclarations.last() as FirProperty
val property = context.containingDeclarations.last() as FirProperty withAnnotationContainer(propertyAccessor) {
withAnnotationContainer(propertyAccessor) { visitWithDeclarationAndReceiver(propertyAccessor, property.name, property.receiverTypeRef)
visitWithDeclarationAndReceiver(propertyAccessor, property.name, property.receiverTypeRef)
}
} }
} }
@@ -1142,7 +1142,12 @@ class DeclarationsConverter(
} }
this.getter = convertedAccessors.find { it.isGetter } this.getter = convertedAccessors.find { it.isGetter }
?: FirDefaultPropertyGetter( ?: 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 { ).also {
it.status = defaultAccessorStatus() it.status = defaultAccessorStatus()
it.initContainingClassAttr() it.initContainingClassAttr()
@@ -1154,7 +1159,7 @@ class DeclarationsConverter(
property.toFirSourceElement(FirFakeSourceElementKind.DefaultAccessor), property.toFirSourceElement(FirFakeSourceElementKind.DefaultAccessor),
moduleData, moduleData,
FirDeclarationOrigin.Source, FirDeclarationOrigin.Source,
returnType, returnType.copyWithNewSourceKind(FirFakeSourceElementKind.DefaultAccessor),
propertyVisibility, symbol, propertyVisibility, symbol,
).also { ).also {
it.status = defaultAccessorStatus() it.status = defaultAccessorStatus()
@@ -314,6 +314,7 @@ class FirFakeSourceElement(psi: PsiElement, override val kind: FirFakeSourceElem
} }
fun FirSourceElement.fakeElement(newKind: FirFakeSourceElementKind): FirSourceElement { fun FirSourceElement.fakeElement(newKind: FirFakeSourceElementKind): FirSourceElement {
if (kind == newKind) return this
return when (this) { return when (this) {
is FirLightSourceElement -> FirLightSourceElement(lighterASTNode, startOffset, endOffset, treeStructure, newKind) is FirLightSourceElement -> FirLightSourceElement(lighterASTNode, startOffset, endOffset, treeStructure, newKind)
is FirPsiSourceElement -> FirFakeSourceElement(psi, 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.EffectiveVisibility
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirImplementationDetail import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirModuleData
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildDefaultSetterValueParameter import org.jetbrains.kotlin.fir.declarations.builder.buildDefaultSetterValueParameter
@@ -126,7 +124,7 @@ class FirDefaultPropertySetter(
FirImplicitUnitTypeRef(source), FirImplicitUnitTypeRef(source),
valueParameters = mutableListOf( valueParameters = mutableListOf(
buildDefaultSetterValueParameter builder@{ buildDefaultSetterValueParameter builder@{
this@builder.source = source this@builder.source = source?.fakeElement(FirFakeSourceElementKind.DefaultAccessor)
this@builder.moduleData = moduleData this@builder.moduleData = moduleData
this@builder.origin = origin this@builder.origin = origin
this@builder.returnTypeRef = propertyTypeRef 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) @Target(AnnotationTarget.PROPERTY_GETTER)
annotation class smartget 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 // FILE: test/AnnotationTargets.java
package test; package test;