FIR checker: report violations related to API mode
This commit is contained in:
committed by
Mikhail Glukhikh
parent
52b247937e
commit
c262f17d75
+24
@@ -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,
|
||||
|
||||
+16
@@ -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
|
||||
}
|
||||
|
||||
+20
@@ -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,
|
||||
|
||||
+6
@@ -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") {
|
||||
|
||||
+2
-1
@@ -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)
|
||||
|
||||
+1
@@ -29,6 +29,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirExpectActualDeclarationChecker,
|
||||
FirInvalidAndDangerousCharactersChecker,
|
||||
FirAmbiguousAnonymousTypeChecker,
|
||||
FirExplicitApiDeclarationChecker,
|
||||
)
|
||||
|
||||
override val functionCheckers: Set<FirFunctionChecker>
|
||||
|
||||
+146
@@ -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
|
||||
}
|
||||
}
|
||||
+9
@@ -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)
|
||||
|
||||
+43
@@ -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.
|
||||
|
||||
+8
-3
@@ -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 }
|
||||
|
||||
-20
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
+8
@@ -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/*"
|
||||
|
||||
Reference in New Issue
Block a user