FIR checker: report violations related to API mode

This commit is contained in:
Tianyu Geng
2021-10-12 02:01:45 +03:00
committed by Mikhail Glukhikh
parent 52b247937e
commit c262f17d75
30 changed files with 298 additions and 222 deletions
@@ -1199,6 +1199,30 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.NO_EXPLICIT_VISIBILITY_IN_API_MODE) { firDiagnostic ->
NoExplicitVisibilityInApiModeImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirErrors.NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING) { firDiagnostic ->
NoExplicitVisibilityInApiModeWarningImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE) { firDiagnostic ->
NoExplicitReturnTypeInApiModeImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING) { firDiagnostic ->
NoExplicitReturnTypeInApiModeWarningImpl(
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirErrors.INLINE_CLASS_NOT_TOP_LEVEL) { firDiagnostic ->
InlineClassNotTopLevelImpl(
firDiagnostic as FirPsiDiagnostic,
@@ -867,6 +867,22 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val message: String
}
abstract class NoExplicitVisibilityInApiMode : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = NoExplicitVisibilityInApiMode::class
}
abstract class NoExplicitVisibilityInApiModeWarning : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = NoExplicitVisibilityInApiModeWarning::class
}
abstract class NoExplicitReturnTypeInApiMode : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = NoExplicitReturnTypeInApiMode::class
}
abstract class NoExplicitReturnTypeInApiModeWarning : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = NoExplicitReturnTypeInApiModeWarning::class
}
abstract class InlineClassNotTopLevel : KtFirDiagnostic<KtDeclaration>() {
override val diagnosticClass get() = InlineClassNotTopLevel::class
}
@@ -1036,6 +1036,26 @@ internal class InapplicableOperatorModifierImpl(
override val token: ValidityToken,
) : KtFirDiagnostic.InapplicableOperatorModifier(), KtAbstractFirDiagnostic<PsiElement>
internal class NoExplicitVisibilityInApiModeImpl(
override val firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.NoExplicitVisibilityInApiMode(), KtAbstractFirDiagnostic<KtDeclaration>
internal class NoExplicitVisibilityInApiModeWarningImpl(
override val firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.NoExplicitVisibilityInApiModeWarning(), KtAbstractFirDiagnostic<KtDeclaration>
internal class NoExplicitReturnTypeInApiModeImpl(
override val firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.NoExplicitReturnTypeInApiMode(), KtAbstractFirDiagnostic<KtDeclaration>
internal class NoExplicitReturnTypeInApiModeWarningImpl(
override val firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.NoExplicitReturnTypeInApiModeWarning(), KtAbstractFirDiagnostic<KtDeclaration>
internal class InlineClassNotTopLevelImpl(
override val firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
@@ -381,6 +381,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val INAPPLICABLE_OPERATOR_MODIFIER by error<PsiElement>(PositioningStrategy.OPERATOR_MODIFIER) {
parameter<String>("message")
}
val NO_EXPLICIT_VISIBILITY_IN_API_MODE by error<KtDeclaration>(PositioningStrategy.DECLARATION_START_TO_NAME)
val NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING by warning<KtDeclaration>(PositioningStrategy.DECLARATION_START_TO_NAME)
val NO_EXPLICIT_RETURN_TYPE_IN_API_MODE by error<KtDeclaration>(PositioningStrategy.DECLARATION_NAME)
val NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING by warning<KtDeclaration>(PositioningStrategy.DECLARATION_NAME)
}
val INLINE_CLASSES by object : DiagnosticGroup("Inline classes") {
@@ -108,8 +108,9 @@ enum class PositioningStrategy(private val strategy: String? = null) {
ENUM_MODIFIER,
FIELD_KEYWORD,
TAILREC_MODIFIER,
IMPORT_ALIAS,
PROPERTY_DELEGATE,
IMPORT_ALIAS,
DECLARATION_START_TO_NAME,
;
@@ -284,6 +284,10 @@ object FirErrors {
val WRONG_MODIFIER_CONTAINING_DECLARATION by error2<PsiElement, KtModifierKeywordToken, String>()
val DEPRECATED_MODIFIER_CONTAINING_DECLARATION by warning2<PsiElement, KtModifierKeywordToken, String>()
val INAPPLICABLE_OPERATOR_MODIFIER by error1<PsiElement, String>(SourceElementPositioningStrategies.OPERATOR_MODIFIER)
val NO_EXPLICIT_VISIBILITY_IN_API_MODE by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_START_TO_NAME)
val NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING by warning0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_START_TO_NAME)
val NO_EXPLICIT_RETURN_TYPE_IN_API_MODE by error0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
val NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING by warning0<KtDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
// Inline classes
val INLINE_CLASS_NOT_TOP_LEVEL by error0<KtDeclaration>(SourceElementPositioningStrategies.INLINE_OR_VALUE_MODIFIER)
@@ -29,6 +29,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirExpectActualDeclarationChecker,
FirInvalidAndDangerousCharactersChecker,
FirAmbiguousAnonymousTypeChecker,
FirExplicitApiDeclarationChecker,
)
override val functionCheckers: Set<FirFunctionChecker>
@@ -0,0 +1,146 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.syntax
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.ExplicitApiMode
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.isLocalMember
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
import org.jetbrains.kotlin.fir.declarations.utils.isData
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.resolve.transformers.publishedApiEffectiveVisibility
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtDeclaration
object FirExplicitApiDeclarationChecker : FirDeclarationSyntaxChecker<FirDeclaration, KtDeclaration>() {
private val codeFragmentTypes =
setOf(KtNodeTypes.BLOCK_CODE_FRAGMENT, KtNodeTypes.EXPRESSION_CODE_FRAGMENT, KtNodeTypes.TYPE_CODE_FRAGMENT)
override fun checkLightTree(element: FirDeclaration, source: FirSourceElement, context: CheckerContext, reporter: DiagnosticReporter) {
if ((source.kind !is FirRealSourceElementKind && source.kind != FirFakeSourceElementKind.PropertyFromParameter) ||
element !is FirMemberDeclaration
) {
return
}
val state = context.session.languageVersionSettings.getFlag(AnalysisFlags.explicitApiMode)
if (state == ExplicitApiMode.DISABLED) return
// Enum entries do not have visibilities
if (element is FirEnumEntry) return
if (!element.effectiveVisibility.publicApi && element.publishedApiEffectiveVisibility == null) return
checkVisibilityModifier(state, element, source, context, reporter)
checkExplicitReturnType(state, element, source, context, reporter)
}
private fun checkVisibilityModifier(
state: ExplicitApiMode,
declaration: FirMemberDeclaration,
source: FirSourceElement,
context: CheckerContext,
reporter: DiagnosticReporter
) {
val visibilityModifier = source.getChild(KtNodeTypes.MODIFIER_LIST)?.getChild(KtTokens.VISIBILITY_MODIFIERS)
if (visibilityModifier != null) return
if (explicitVisibilityIsNotRequired(declaration, context)) return
val factory = if (state == ExplicitApiMode.STRICT)
FirErrors.NO_EXPLICIT_VISIBILITY_IN_API_MODE
else
FirErrors.NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING
reporter.reportOn(source, factory, context)
}
/**
* Exclusion list:
* 1. Primary constructors of public API classes
* 2. Properties of data classes in public API
* 3. Overrides of public API. Effectively, this means 'no report on overrides at all'
* 4. Getters and setters (because getters can't change visibility and setter-only explicit visibility looks ugly)
* 5. Properties of annotations in public API
* 6. Value parameter declaration
*
* TODO: Do we need something like @PublicApiFile to disable (or invert) this inspection per-file?
*/
private fun explicitVisibilityIsNotRequired(declaration: FirMemberDeclaration, context: CheckerContext): Boolean {
return when (declaration) {
// 1,
is FirPrimaryConstructor,
// 4
is FirPropertyAccessor,
// 6
is FirValueParameter -> true
is FirCallableDeclaration -> {
val containingClass = context.containingDeclarations.lastOrNull() as? FirRegularClass
// 2, 5
if (declaration is FirProperty &&
containingClass != null &&
(containingClass.isData || containingClass.classKind == ClassKind.ANNOTATION_CLASS)
) {
return true
}
// 3
declaration.isOverride
}
else -> false
}
}
private fun checkExplicitReturnType(
state: ExplicitApiMode,
declaration: FirMemberDeclaration,
source: FirSourceElement,
context: CheckerContext,
reporter: DiagnosticReporter
) {
if (declaration !is FirCallableDeclaration) return
if (!returnTypeCheckIsApplicable(source, context)) return
val shouldReport = returnTypeRequired(declaration, context)
if (shouldReport) {
val factory =
if (state == ExplicitApiMode.STRICT)
FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE
else
FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING
reporter.reportOn(source, factory, context)
}
}
private fun returnTypeCheckIsApplicable(source: FirSourceElement, context: CheckerContext): Boolean {
// Note that by default getChild uses `depth = -1`, which would find all descendents.
if (source.getChild(KtNodeTypes.TYPE_REFERENCE, depth = 1) != null) return false
// Do not check if the containing file is not a physical file.
val containingFile = context.containingDeclarations.first()
if (containingFile.source?.elementType in codeFragmentTypes) return false
return when (source.elementType) {
// Only require return type if the function is defined via `=`. If it has a block body or is abstract, we don't require return
// type because not declaring means it returns `Unit`.
KtNodeTypes.FUN -> source.getChild(KtTokens.EQ, depth = 1) != null
KtNodeTypes.PROPERTY -> true
else -> false
}
}
private fun returnTypeRequired(declaration: FirCallableDeclaration, context: CheckerContext): Boolean {
// If current declaration is local or it's a member in a local declaration (local class, etc), then we do not require return type.
return !declaration.isLocalMember && context.containingDeclarations.lastOrNull()?.isLocalMember != true
}
}
@@ -308,6 +308,10 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_CLASS_M
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ACTUAL_FOR_EXPECT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_COMPANION_OBJECT
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_ELSE_IN_WHEN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_EXPLICIT_VISIBILITY_IN_API_MODE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_GET_METHOD
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_RECEIVER_ALLOWED
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY
@@ -799,6 +803,11 @@ class FirDefaultErrorMessages {
map.put(DEPRECATED_MODIFIER_PAIR, "Modifier ''{0}'' is deprecated in presence of ''{1}''", TO_STRING, TO_STRING)
map.put(DEPRECATED_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is deprecated for ''{1}''", TO_STRING, STRING)
map.put(REDUNDANT_MODIFIER_FOR_TARGET, "Modifier ''{0}'' is redundant for ''{1}''", TO_STRING, STRING)
map.put(NO_EXPLICIT_VISIBILITY_IN_API_MODE, "Visibility must be specified in explicit API mode");
map.put(NO_EXPLICIT_RETURN_TYPE_IN_API_MODE, "Return type must be specified in explicit API mode");
map.put(NO_EXPLICIT_VISIBILITY_IN_API_MODE_WARNING, "Visibility must be specified in explicit API mode");
map.put(NO_EXPLICIT_RETURN_TYPE_IN_API_MODE_WARNING, "Return type must be specified in explicit API mode");
map.put(INCOMPATIBLE_MODIFIERS, "Modifier ''{0}'' is incompatible with ''{1}''", TO_STRING, TO_STRING)
map.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members")
map.put(WRONG_MODIFIER_TARGET, "Modifier ''{0}'' is not applicable to ''{1}''", TO_STRING, STRING)
@@ -148,6 +148,43 @@ object LightTreePositioningStrategies {
}
}
val DECLARATION_START_TO_NAME: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
private fun FlyweightCapableTreeStructure<LighterASTNode>.firstNonCommentNonAnnotationLeaf(node: LighterASTNode): LighterASTNode? {
val childrenArray = getChildrenArray(node).filterNotNull()
// this is leaf
if (childrenArray.isEmpty()) return node
for (child in childrenArray) {
val childTokenType = child.tokenType ?: return null
if (childTokenType in KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET || childTokenType == KtNodeTypes.ANNOTATION_ENTRY) {
continue
}
return firstNonCommentNonAnnotationLeaf(child) ?: continue
}
return null
}
override fun mark(
node: LighterASTNode,
startOffset: Int,
endOffset: Int,
tree: FlyweightCapableTreeStructure<LighterASTNode>
): List<TextRange> {
val startNode = tree.firstNonCommentNonAnnotationLeaf(node) ?: node
val nameIdentifier = tree.nameIdentifier(node)
return if (nameIdentifier != null) {
markRange(startNode, nameIdentifier, startOffset, endOffset, tree, node)
} else {
val endNode = when (node.tokenType) {
KtNodeTypes.PRIMARY_CONSTRUCTOR, KtNodeTypes.SECONDARY_CONSTRUCTOR -> tree.constructorKeyword(node)
KtNodeTypes.OBJECT_DECLARATION -> tree.objectKeyword(node)
else -> return DEFAULT.mark(node, startOffset, endOffset, tree)
}
markRange(startNode, endNode ?: node, startOffset, endOffset, tree, node)
}
}
}
val DECLARATION_NAME: LightTreePositioningStrategy = object : LightTreePositioningStrategy() {
override fun mark(
node: LighterASTNode,
@@ -1083,6 +1120,12 @@ fun LighterASTNode.isExpression(): Boolean {
}
}
fun FlyweightCapableTreeStructure<LighterASTNode>.getChildrenArray(node: LighterASTNode): Array<LighterASTNode?> {
val childrenRef = Ref<Array<LighterASTNode?>>()
getChildren(node, childrenRef)
return childrenRef.get() ?: emptyArray()
}
/**
* @param locateReferencedName whether to remove any nested parentheses while locating the reference element. This is useful for diagnostics
* on super and unresolved references. For example, with the following, only the part inside the parentheses should be highlighted.
@@ -330,13 +330,18 @@ object SourceElementPositioningStrategies {
PositioningStrategies.TAILREC_MODIFIER
)
val PROPERTY_DELEGATE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.PROPERTY_DELEGATE,
PositioningStrategies.PROPERTY_DELEGATE
)
val IMPORT_ALIAS = SourceElementPositioningStrategy(
LightTreePositioningStrategies.IMPORT_ALIAS,
PositioningStrategies.IMPORT_ALIAS
)
val PROPERTY_DELEGATE = SourceElementPositioningStrategy(
LightTreePositioningStrategies.PROPERTY_DELEGATE,
PositioningStrategies.PROPERTY_DELEGATE
val DECLARATION_START_TO_NAME = SourceElementPositioningStrategy(
LightTreePositioningStrategies.DECLARATION_START_TO_NAME,
PositioningStrategies.DECLARATION_START_TO_NAME
)
}
@@ -1,47 +0,0 @@
// SKIP_TXT
annotation class A
@Target(
AnnotationTarget.CLASS,
AnnotationTarget.PROPERTY,
AnnotationTarget.CONSTRUCTOR,
AnnotationTarget.FUNCTION
)
public annotation class B
annotation class C(val a: String)
/**
* Foo1 KDoc
*/
@B
class Foo1() {}
public class Foo2() {
/**
* KDoc for methodWithAnnotations
*/
@B
fun methodWithAnnotations() {}
/**
* Property KDoc
*/
@B
var simple: Int = 10
}
public open class ClassWithOpen {
/**
* constructor KDoc
*/
@B
constructor() {}
/**
* KDoc for openAnnotatedMethod
*/
@B
open fun openAnnotatedMethod() {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// SKIP_TXT
<!NO_EXPLICIT_VISIBILITY_IN_API_MODE!>annotation class A<!>
@@ -1,47 +0,0 @@
// SKIP_TXT
/**
* KDoc for Foo1
*/
class Foo1() {}
public class Foo2() {
/**
* KDoc for method
*/
fun method() {}
/**
* KDoc for method2
*/
public fun method2() {}
private fun method3() {}
fun implicit() = 10
public fun implicit2() = 10
public fun implicit3(): Int = 10
}
public open class ClassWithOpen() {
/**
* KDoc for method
*/
fun method() {}
/**
* KDoc for openMethod
*/
open fun openMethod() {}
}
public data class FooData(val i: Int, val s: String)
data class FooData2(val i: Int, val s: String)
public class WithNested {
class Nested {}
inner class Inner {}
}
enum class Foo { A, B }
public enum class Bar { A, B }
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// SKIP_TXT
/**
@@ -44,4 +45,4 @@ public class WithNested {
}
<!NO_EXPLICIT_VISIBILITY_IN_API_MODE!>enum class Foo<!> { A, B }
public enum class Bar { A, B }
public enum class Bar { A, B }
@@ -1,20 +0,0 @@
// SKIP_TXT
public class Bar {
companion object {}
}
public class Bar2 {
companion object MyCompanion {}
}
public class Bar3 {
/**
* Nested object KDoc
*/
object NestedObject {}
}
data class FooData2(val i: Int, val s: String) {
object NestedObject {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// SKIP_TXT
public class Bar {
@@ -1,17 +0,0 @@
// SKIP_TXT
public class Foo1 () {}
public class Foo2 constructor() {}
public class Foo3 public constructor() {}
public class Foo4 private constructor() {}
public class Foo5 {
/**
* constructor KDoc
*/
constructor() {}
}
public class Foo6 {
public constructor() {}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// SKIP_TXT
public class Foo1 () {}
@@ -1,8 +0,0 @@
// !DIAGNOSTICS: -EXPERIMENTAL_FEATURE_WARNING
// !LANGUAGE: -JvmInlineValueClasses
// SKIP_TXT
inline class Value1(val inner: Int)
public inline class Value2(val inner: Int)
inline class Value3(public val inner: Int)
public inline class Value4(public val inner: Int)
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -EXPERIMENTAL_FEATURE_WARNING
// !LANGUAGE: -JvmInlineValueClasses
// SKIP_TXT
@@ -5,4 +6,4 @@
<!NO_EXPLICIT_VISIBILITY_IN_API_MODE!>inline class Value1<!>(<!NO_EXPLICIT_VISIBILITY_IN_API_MODE!>val inner<!>: Int)
public inline class Value2(<!NO_EXPLICIT_VISIBILITY_IN_API_MODE!>val inner<!>: Int)
<!NO_EXPLICIT_VISIBILITY_IN_API_MODE!>inline class Value3<!>(public val inner: Int)
public inline class Value4(public val inner: Int)
public inline class Value4(public val inner: Int)
@@ -1,35 +0,0 @@
// SKIP_TXT
interface I1 {
fun i()
}
public interface I2 {
fun i()
}
public interface I3 {
public fun i()
public val v: Int
}
public interface I4 {
public fun i(): Int
public val v: Int
}
public class Impl: I3 {
override fun i() {}
override val v: Int
get() = 10
}
public class Impl2: I4 {
override fun i() = 10
override val v = 10
}
private class PrivateImpl: I4 {
override fun i() = 10
override val v = 10
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// SKIP_TXT
<!NO_EXPLICIT_VISIBILITY_IN_API_MODE!>interface I1<!> {
@@ -1,23 +0,0 @@
// SKIP_TXT
public class Foo(val bar: Int, private var bar2: String, internal var bar3: Long, public var bar4: Int) {
/**
* Property KDoc
*/
var simple: Int = 10
public var simple2: Int = 10
val withGetter: Int
get() = 10
public val withGetter2: Int
get() = 10
var getterAndSetter: Int = 10
get() = field
set(v) { field = v }
public var getterAndSetter2: Int = 10
get() = field
set(v) { field = v }
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// SKIP_TXT
public class Foo(<!NO_EXPLICIT_VISIBILITY_IN_API_MODE!>val bar<!>: Int, private var bar2: String, internal var bar3: Long, public var bar4: Int) {
@@ -1,7 +0,0 @@
// SKIP_TXT
// WITH_RUNTIME
public class A {
@PublishedApi
internal fun foo() = 1
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// SKIP_TXT
// WITH_RUNTIME
@@ -1,12 +0,0 @@
// SKIP_TXT
/**
* foo KDoc
*/
fun foo() {}
public fun foo2() {}
fun bar() = 10
public fun bar2() = 10
public fun bar3(): Int = 10
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// SKIP_TXT
/**
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.test.runners
import org.jetbrains.kotlin.config.ExplicitApiMode
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.test.Constructor
import org.jetbrains.kotlin.test.TestJdkKind
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.test.directives.FirDiagnosticsDirectives.WITH_EXTEND
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.JDK_KIND
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.WITH_REFLECT
import org.jetbrains.kotlin.test.directives.JvmEnvironmentConfigurationDirectives.WITH_STDLIB
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives.LANGUAGE
import org.jetbrains.kotlin.test.frontend.fir.FirFailingTestSuppressor
import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
@@ -108,6 +110,12 @@ fun TestConfigurationBuilder.baseFirDiagnosticTestConfiguration(
}
}
forTestsMatching("compiler/testData/diagnostics/tests/testsWithExplicitApi/*") {
defaultDirectives {
LanguageSettingsDirectives.EXPLICIT_API_MODE with ExplicitApiMode.STRICT
}
}
forTestsMatching(
"compiler/fir/analysis-tests/testData/resolve/extendedCheckers/*" or
"compiler/testData/diagnostics/tests/controlFlowAnalysis/deadCode/*"