From f44acf4f448c65f4cf54c2dcb4313eb59189a77b Mon Sep 17 00:00:00 2001
From: Evgeny Mandrikov <138671+Godin@users.noreply.github.com>
Date: Fri, 29 Nov 2024 14:56:11 +0100
Subject: [PATCH] SONARKT-400 Integrate kotlin-analysis-api
---
build.gradle.kts | 5 +
gradle/verification-metadata.xml | 40 ++++++
sonar-kotlin-api/build.gradle.kts | 21 +++
.../org/sonarsource/kotlin/api/frontend/K1.kt | 126 +++++++++++++++++
.../org/sonarsource/kotlin/api/frontend/K2.kt | 133 ++++++++++++++++++
.../frontend/KotlinCoreEnvironmentTools.kt | 12 +-
.../kotlin/api/frontend/KotlinFileContext.kt | 4 +
.../kotlin/api/frontend/KotlinTree.kt | 10 +-
...ModuleProviderByCompilerConfiguration.java | 51 +++++++
.../AbstractKotlinSensorExecuteContext.kt | 4 +-
.../kotlin/api/visiting/KotlinFileVisitor.kt | 37 ++++-
.../KotlinCoreEnvironmentToolsTest.kt | 66 +++++++++
.../api/sensors/AbstractKotlinSensorTest.kt | 1 +
.../kotlin/checks/AnchorPrecedenceCheck.kt | 1 +
.../kotlin/checks/AndroidBroadcastingCheck.kt | 1 +
.../checks/ArrayHashCodeAndToStringCheck.kt | 1 +
.../AuthorisingNonAuthenticatedUsersCheck.kt | 1 +
.../checks/BiometricAuthWithoutCryptoCheck.kt | 1 +
.../kotlin/checks/CipherBlockChainingCheck.kt | 1 +
.../kotlin/checks/CipherModeOperationCheck.kt | 1 +
.../kotlin/checks/ClearTextProtocolCheck.kt | 1 +
.../checks/CollectionCallingItselfCheck.kt | 1 +
.../CollectionInappropriateCallsCheck.kt | 1 +
.../CollectionShouldBeImmutableCheck.kt | 1 +
.../CollectionSizeAndArrayLengthCheck.kt | 1 +
.../CoroutineScopeFunSuspendingCheck.kt | 1 +
.../checks/CoroutinesTimeoutApiUnusedCheck.kt | 1 +
.../kotlin/checks/DataHashingCheck.kt | 1 +
.../kotlin/checks/DebugFeatureEnabledCheck.kt | 1 +
.../kotlin/checks/DelegationPatternCheck.kt | 1 +
.../kotlin/checks/DeprecatedCodeCheck.kt | 1 +
.../kotlin/checks/DeprecatedCodeUsedCheck.kt | 1 +
.../kotlin/checks/DuplicateBranchCheck.kt | 1 +
.../checks/DuplicatesInCharacterClassCheck.kt | 1 +
.../kotlin/checks/EmptyLineRegexCheck.kt | 1 +
.../checks/EmptyStringRepetitionCheck.kt | 1 +
.../kotlin/checks/EncryptionAlgorithmCheck.kt | 1 +
.../kotlin/checks/EqualsArgumentTypeCheck.kt | 1 +
.../kotlin/checks/EqualsMethodUsageCheck.kt | 1 +
.../EqualsOverriddenWithArrayFieldCheck.kt | 1 +
.../EqualsOverridenWithHashCodeCheck.kt | 1 +
.../kotlin/checks/ExposedMutableFlowCheck.kt | 1 +
.../ExternalAndroidStorageAccessCheck.kt | 1 +
.../kotlin/checks/FinalFlowOperationCheck.kt | 1 +
...wChannelReturningFunsNotSuspendingCheck.kt | 1 +
.../checks/GraphemeClustersInClassesCheck.kt | 1 +
.../checks/IgnoredOperationStatusCheck.kt | 1 +
.../kotlin/checks/IndexedAccessCheck.kt | 1 +
.../checks/InjectableDispatchersCheck.kt | 1 +
.../checks/InterfaceCouldBeFunctionalCheck.kt | 1 +
.../kotlin/checks/InvalidRegexCheck.kt | 1 +
.../kotlin/checks/IsInstanceMethodCheck.kt | 1 +
.../kotlin/checks/LiftReturnStatementCheck.kt | 1 +
.../kotlin/checks/MainSafeCoroutinesCheck.kt | 1 +
.../MapValuesShouldBeAccessedSafelyCheck.kt | 1 +
.../MobileDatabaseEncryptionKeysCheck.kt | 1 +
.../PreparedStatementAndResultSetCheck.kt | 1 +
.../PropertyGetterAndSetterUsageCheck.kt | 1 +
.../kotlin/checks/PseudoRandomCheck.kt | 1 +
.../kotlin/checks/ReasonableTypeCastsCheck.kt | 1 +
.../kotlin/checks/ReceivingIntentsCheck.kt | 1 +
.../RedundantMethodsInDataClassesCheck.kt | 1 +
.../checks/RedundantSuspendModifierCheck.kt | 1 +
.../kotlin/checks/RedundantTypeCastsCheck.kt | 1 +
.../kotlin/checks/RegexComplexityCheck.kt | 1 +
.../kotlin/checks/ReluctantQuantifierCheck.kt | 1 +
.../checks/ReplaceGuavaWithKotlinCheck.kt | 1 +
.../checks/RobustCryptographicKeysCheck.kt | 1 +
.../kotlin/checks/RunFinalizersCheck.kt | 1 +
.../kotlin/checks/SamConversionCheck.kt | 1 +
.../ScheduledThreadPoolExecutorZeroCheck.kt | 1 +
.../kotlin/checks/ServerCertificateCheck.kt | 1 +
.../checks/SimplifiedPreconditionsCheck.kt | 1 +
...fyFilteringBeforeTerminalOperationCheck.kt | 1 +
.../checks/SimplifySizeExpressionCheck.kt | 1 +
.../kotlin/checks/SingletonPatternCheck.kt | 1 +
.../kotlin/checks/StreamNotConsumedCheck.kt | 1 +
.../checks/StrongCipherAlgorithmCheck.kt | 1 +
.../StructuredConcurrencyPrinciplesCheck.kt | 1 +
.../SuspendingFunCallerDispatcherCheck.kt | 1 +
.../UnencryptedDatabaseOnMobileCheck.kt | 1 +
...encryptedFilesInMobileApplicationsCheck.kt | 1 +
.../checks/UnicodeAwareCharClassesCheck.kt | 1 +
.../kotlin/checks/UnnecessaryImportsCheck.kt | 1 +
.../checks/UnpredictableHashSaltCheck.kt | 1 +
.../UnpredictableSecureRandomSaltCheck.kt | 1 +
...itedFindFunctionWithNullComparisonCheck.kt | 1 +
.../checks/UnusedDeferredResultCheck.kt | 1 +
.../kotlin/checks/UnusedLocalVariableCheck.kt | 1 +
.../kotlin/checks/UnusedPrivateMethodCheck.kt | 1 +
.../kotlin/checks/UselessAssignmentsCheck.kt | 1 +
.../kotlin/checks/UselessIncrementCheck.kt | 1 +
.../kotlin/checks/UselessNullCheckCheck.kt | 1 +
.../kotlin/checks/VarShouldBeValCheck.kt | 1 +
.../checks/VerifiedServerHostnamesCheck.kt | 1 +
.../ViewModelSuspendingFunctionsCheck.kt | 1 +
.../kotlin/checks/VoidShouldBeUnitCheck.kt | 1 +
.../kotlin/checks/WeakSSLContextCheck.kt | 1 +
.../checks/WebViewJavaScriptSupportCheck.kt | 1 +
.../kotlin/checks/WebViewsFileAccessCheck.kt | 1 +
.../sonarsource/kotlin/checks/CheckTest.kt | 18 ++-
.../kotlin/gradle/KotlinGradleSensor.kt | 1 +
sonar-kotlin-plugin/build.gradle.kts | 8 +-
.../sonarsource/kotlin/plugin/KotlinSensor.kt | 2 +
.../linking/WorkaroundForJarMinimization.java | 12 ++
.../kotlin/plugin/KotlinSensorTest.kt | 20 ++-
.../WorkaroundForJarMinimizationTest.kt | 2 +-
.../kotlin/testapi/KotlinVerifier.kt | 4 +-
.../sonarsource/kotlin/testapi/TestUtils.kt | 21 ++-
109 files changed, 674 insertions(+), 11 deletions(-)
create mode 100644 sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/K1.kt
create mode 100644 sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/K2.kt
create mode 100644 sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KtModuleProviderByCompilerConfiguration.java
diff --git a/build.gradle.kts b/build.gradle.kts
index ee609d79e..e12330f28 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -87,6 +87,11 @@ allprojects {
repositories {
mavenCentral()
+ maven(url = "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide-plugin-dependencies") {
+ content {
+ includeGroup("org.jetbrains.kotlin")
+ }
+ }
}
}
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 72e832da3..2ee32e075 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -805,6 +805,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1430,6 +1460,16 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/sonar-kotlin-api/build.gradle.kts b/sonar-kotlin-api/build.gradle.kts
index 810fb649a..8830878b5 100644
--- a/sonar-kotlin-api/build.gradle.kts
+++ b/sonar-kotlin-api/build.gradle.kts
@@ -3,6 +3,27 @@ plugins {
}
dependencies {
+ listOf(
+ // Source of these artifacts is
+ // https://github.com/JetBrains/kotlin/tree/v2.0.21/prepare/ide-plugin-dependencies
+ // where ones whose name contains "high-level" are deprecated and should not be used - see
+ // https://github.com/JetBrains/kotlin/commit/3ad9798a17ad9eb68cdb1e9f8f1a69584151bfd4
+ "org.jetbrains.kotlin:analysis-api-standalone-for-ide",
+ "org.jetbrains.kotlin:analysis-api-platform-interface-for-ide",
+ "org.jetbrains.kotlin:analysis-api-for-ide", // old name "high-level-api-for-ide"
+ "org.jetbrains.kotlin:analysis-api-impl-base-for-ide", // old name "high-level-api-impl-base"
+ "org.jetbrains.kotlin:analysis-api-fe10-for-ide", // old name "high-level-api-fe10"
+ "org.jetbrains.kotlin:analysis-api-k2-for-ide", // old name "high-level-api-k2"
+ "org.jetbrains.kotlin:low-level-api-fir-for-ide",
+ "org.jetbrains.kotlin:symbol-light-classes-for-ide"
+ ).forEach {
+ val kotlinVersion: String by project.ext
+ api("$it:$kotlinVersion") {
+ // https://youtrack.jetbrains.com/issue/KT-61639/Standalone-Analysis-API-cannot-find-transitive-dependencies
+ isTransitive = false
+ }
+ }
+
compileOnly(libs.sonar.plugin.api)
compileOnly(libs.slf4j.api)
implementation(libs.sonar.analyzer.commons)
diff --git a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/K1.kt b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/K1.kt
new file mode 100644
index 000000000..e20daa070
--- /dev/null
+++ b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/K1.kt
@@ -0,0 +1,126 @@
+/*
+ * SonarSource Kotlin
+ * Copyright (C) 2018-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Sonar Source-Available License for more details.
+ *
+ * You should have received a copy of the Sonar Source-Available License
+ * along with this program; if not, see https://sonarsource.com/license/ssal/
+ */
+package org.sonarsource.kotlin.api.frontend
+
+import com.intellij.core.CoreApplicationEnvironment
+import com.intellij.mock.MockApplication
+import com.intellij.mock.MockProject
+import com.intellij.openapi.Disposable
+import com.intellij.psi.ClassTypePointerFactory
+import com.intellij.psi.impl.smartPointers.PsiClassReferenceTypePointerFactory
+import org.jetbrains.kotlin.analysis.api.KaAnalysisNonPublicApi
+import org.jetbrains.kotlin.analysis.api.descriptors.CliFe10AnalysisFacade
+import org.jetbrains.kotlin.analysis.api.descriptors.Fe10AnalysisFacade
+import org.jetbrains.kotlin.analysis.api.descriptors.KaFe10AnalysisHandlerExtension
+import org.jetbrains.kotlin.analysis.api.platform.lifetime.KotlinAlwaysAccessibleLifetimeTokenProvider
+import org.jetbrains.kotlin.analysis.api.platform.lifetime.KotlinLifetimeTokenProvider
+import org.jetbrains.kotlin.analysis.api.platform.modification.KotlinGlobalModificationService
+import org.jetbrains.kotlin.analysis.api.platform.modification.KotlinModificationTrackerFactory
+import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinByModulesResolutionScopeProvider
+import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinProjectStructureProvider
+import org.jetbrains.kotlin.analysis.api.platform.projectStructure.KotlinResolutionScopeProvider
+import org.jetbrains.kotlin.analysis.api.standalone.base.modification.KotlinStandaloneGlobalModificationService
+import org.jetbrains.kotlin.analysis.api.standalone.base.modification.KotlinStandaloneModificationTrackerFactory
+import org.jetbrains.kotlin.analysis.api.standalone.base.projectStructure.AnalysisApiSimpleServiceRegistrar
+import org.jetbrains.kotlin.analysis.api.standalone.base.projectStructure.PluginStructureProvider
+import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
+import org.jetbrains.kotlin.references.fe10.base.DummyKtFe10ReferenceResolutionHelper
+import org.jetbrains.kotlin.references.fe10.base.KtFe10ReferenceResolutionHelper
+import org.jetbrains.kotlin.resolve.extensions.AnalysisHandlerExtension
+
+/**
+ * Marker indicating that
+ * annotated [org.sonarsource.kotlin.api.checks.KotlinCheck]
+ * can be executed only in K1 mode.
+ */
+annotation class K1only
+
+internal fun configureK1AnalysisApiServices(env: KotlinCoreEnvironment) {
+ val application = env.projectEnvironment.environment.application
+ if (application.getServiceIfCreated(KtFe10ReferenceResolutionHelper::class.java) == null) {
+ AnalysisApiFe10ServiceRegistrar.registerApplicationServices(application)
+ }
+ val project = env.projectEnvironment.project
+ AnalysisApiFe10ServiceRegistrar.registerProjectServices(project)
+ AnalysisApiFe10ServiceRegistrar.registerProjectModelServices(
+ project,
+ env.projectEnvironment.parentDisposable
+ )
+
+ project.registerService(
+ KotlinModificationTrackerFactory::class.java,
+ KotlinStandaloneModificationTrackerFactory::class.java,
+ )
+ project.registerService(
+ KotlinGlobalModificationService::class.java,
+ KotlinStandaloneGlobalModificationService::class.java,
+ )
+ project.registerService(
+ KotlinLifetimeTokenProvider::class.java,
+ KotlinAlwaysAccessibleLifetimeTokenProvider::class.java,
+ )
+ project.registerService(
+ KotlinResolutionScopeProvider::class.java,
+ KotlinByModulesResolutionScopeProvider::class.java,
+ );
+ project.registerService(
+ KotlinProjectStructureProvider::class.java,
+ KtModuleProviderByCompilerConfiguration.build(
+ env.projectEnvironment,
+ env.configuration,
+ listOf()
+ )
+ )
+}
+
+@OptIn(KaAnalysisNonPublicApi::class)
+private object AnalysisApiFe10ServiceRegistrar : AnalysisApiSimpleServiceRegistrar() {
+ private const val PLUGIN_RELATIVE_PATH = "/META-INF/analysis-api/analysis-api-fe10.xml"
+
+ override fun registerApplicationServices(application: MockApplication) {
+ PluginStructureProvider.registerApplicationServices(application, PLUGIN_RELATIVE_PATH)
+ application.registerService(
+ KtFe10ReferenceResolutionHelper::class.java,
+ DummyKtFe10ReferenceResolutionHelper,
+ )
+ val applicationArea = application.extensionArea
+ if (!applicationArea.hasExtensionPoint(ClassTypePointerFactory.EP_NAME)) {
+ CoreApplicationEnvironment.registerApplicationExtensionPoint(
+ ClassTypePointerFactory.EP_NAME,
+ ClassTypePointerFactory::class.java,
+ )
+ applicationArea
+ .getExtensionPoint(ClassTypePointerFactory.EP_NAME)
+ .registerExtension(PsiClassReferenceTypePointerFactory(), application)
+ }
+ }
+
+ override fun registerProjectExtensionPoints(project: MockProject) {
+ AnalysisHandlerExtension.registerExtensionPoint(project)
+ PluginStructureProvider.registerProjectExtensionPoints(project, PLUGIN_RELATIVE_PATH)
+ }
+
+ override fun registerProjectServices(project: MockProject) {
+ PluginStructureProvider.registerProjectServices(project, PLUGIN_RELATIVE_PATH)
+ PluginStructureProvider.registerProjectListeners(project, PLUGIN_RELATIVE_PATH)
+ }
+
+ override fun registerProjectModelServices(project: MockProject, disposable: Disposable) {
+ project.apply { registerService(Fe10AnalysisFacade::class.java, CliFe10AnalysisFacade()) }
+ AnalysisHandlerExtension.registerExtension(project, KaFe10AnalysisHandlerExtension())
+ }
+}
diff --git a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/K2.kt b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/K2.kt
new file mode 100644
index 000000000..a46aa10f8
--- /dev/null
+++ b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/K2.kt
@@ -0,0 +1,133 @@
+/*
+ * SonarSource Kotlin
+ * Copyright (C) 2018-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Sonar Source-Available License for more details.
+ *
+ * You should have received a copy of the Sonar Source-Available License
+ * along with this program; if not, see https://sonarsource.com/license/ssal/
+ */
+package org.sonarsource.kotlin.api.frontend
+
+import com.intellij.openapi.Disposable
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.openapi.vfs.VirtualFileSystem
+import com.intellij.openapi.vfs.local.CoreLocalFileSystem
+import org.jetbrains.kotlin.analysis.api.standalone.StandaloneAnalysisAPISession
+import org.jetbrains.kotlin.analysis.api.standalone.buildStandaloneAnalysisAPISession
+import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtLibraryModule
+import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtSdkModule
+import org.jetbrains.kotlin.analysis.project.structure.builder.buildKtSourceModule
+import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl
+import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
+import org.jetbrains.kotlin.config.CompilerConfiguration
+import org.jetbrains.kotlin.config.JVMConfigurationKeys
+import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager
+import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
+import java.io.File
+import java.io.InputStream
+import java.io.OutputStream
+
+/**
+ * @see [org.jetbrains.kotlin.analysis.api.standalone.StandaloneAnalysisAPISessionBuilder.buildKtModuleProviderByCompilerConfiguration]
+ */
+fun createK2AnalysisSession(
+ parentDisposable: Disposable,
+ compilerConfiguration: CompilerConfiguration,
+ virtualFiles: Collection,
+): StandaloneAnalysisAPISession {
+ return buildStandaloneAnalysisAPISession(
+ projectDisposable = parentDisposable,
+ ) {
+ // https://github.com/JetBrains/kotlin/blob/a9ff22693479cabd201909a06e6764c00eddbf7b/analysis/analysis-api-fe10/tests/org/jetbrains/kotlin/analysis/api/fe10/test/configurator/AnalysisApiFe10TestServiceRegistrar.kt#L49
+ registerProjectService(ModuleVisibilityManager::class.java, CliModuleVisibilityManagerImpl(enabled = true))
+
+ // TODO language version, jvm target, etc
+ val platform = JvmPlatforms.defaultJvmPlatform
+ buildKtModuleProvider {
+ this.platform = platform
+ addModule(buildKtSourceModule {
+ this.platform = platform
+ moduleName = "module"
+ addSourceVirtualFiles(virtualFiles)
+ addRegularDependency(buildKtLibraryModule {
+ this.platform = platform
+ libraryName = "library"
+ addBinaryRoots(compilerConfiguration.jvmClasspathRoots.map { it.toPath() })
+ })
+ compilerConfiguration[JVMConfigurationKeys.JDK_HOME]?.let { jdkHome ->
+ addRegularDependency(buildKtSdkModule {
+ this.platform = platform
+ addBinaryRootsFromJdkHome(jdkHome.toPath(), isJre = false)
+ libraryName = "JDK"
+ })
+ }
+ })
+ }
+ }
+}
+
+class KotlinFileSystem : CoreLocalFileSystem() {
+ /**
+ * TODO return null if file does not exist - see [CoreLocalFileSystem.findFileByNioFile]
+ */
+ override fun findFileByPath(path: String): VirtualFile? =
+ KotlinVirtualFile(this, File(path))
+}
+
+class KotlinVirtualFile(
+ private val fileSystem: KotlinFileSystem,
+ private val file: File,
+ private val content: String? = null,
+) : VirtualFile() {
+
+ override fun getName(): String = file.name
+
+ override fun getFileSystem(): VirtualFileSystem = fileSystem
+
+ override fun getPath(): String = FileUtil.toSystemIndependentName(file.absolutePath)
+
+ override fun isWritable(): Boolean = false
+
+ override fun isDirectory(): Boolean = file.isDirectory
+
+ override fun isValid(): Boolean = true
+
+ override fun getParent(): VirtualFile? {
+ val parentFile = file.parentFile ?: return null
+ return KotlinVirtualFile(fileSystem, parentFile)
+ }
+
+ override fun getChildren(): Array {
+ if (file.isFile || !file.exists()) return emptyArray()
+ throw UnsupportedOperationException("getChildren " + file.absolutePath)
+ }
+
+ override fun getOutputStream(p0: Any?, p1: Long, p2: Long): OutputStream =
+ throw UnsupportedOperationException()
+
+ override fun contentsToByteArray(): ByteArray {
+ if (content != null) return content.toByteArray()
+ return FileUtil.loadFileBytes(file)
+ }
+
+ override fun getTimeStamp(): Long =
+ throw UnsupportedOperationException()
+
+ override fun getLength(): Long = file.length()
+
+ override fun refresh(p0: Boolean, p1: Boolean, p2: Runnable?) =
+ throw UnsupportedOperationException()
+
+ override fun getInputStream(): InputStream =
+ throw UnsupportedOperationException()
+
+}
diff --git a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinCoreEnvironmentTools.kt b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinCoreEnvironmentTools.kt
index c5638c51a..e6668570d 100644
--- a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinCoreEnvironmentTools.kt
+++ b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinCoreEnvironmentTools.kt
@@ -26,7 +26,7 @@ import org.jetbrains.kotlin.cli.jvm.compiler.NoScopeRecordCliBindingTrace
import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import com.intellij.openapi.Disposable
-import com.intellij.openapi.util.Disposer
+import org.jetbrains.kotlin.analysis.api.standalone.StandaloneAnalysisAPISession
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -52,10 +52,20 @@ class Environment(
val classpath: List,
kotlinLanguageVersion: LanguageVersion,
javaLanguageVersion: JvmTarget = JvmTarget.JVM_1_8,
+ val useK2: Boolean = false,
) {
val configuration = compilerConfiguration(classpath, kotlinLanguageVersion, javaLanguageVersion)
+ // K1
val env = kotlinCoreEnvironment(configuration, disposable)
val ktPsiFactory: KtPsiFactory = KtPsiFactory(env.project, false)
+ // K2
+ var k2session: StandaloneAnalysisAPISession? = null
+
+ init {
+ if (!useK2) {
+ configureK1AnalysisApiServices(env)
+ }
+ }
}
fun kotlinCoreEnvironment(
diff --git a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinFileContext.kt b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinFileContext.kt
index 943920efd..b577cfd97 100644
--- a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinFileContext.kt
+++ b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinFileContext.kt
@@ -27,6 +27,10 @@ import org.sonarsource.kotlin.api.reporting.SecondaryLocation
data class KotlinFileContext(
val inputFileContext: InputFileContext,
val ktFile: KtFile,
+ /**
+ * @see [org.sonarsource.kotlin.api.visiting.withKaSession]
+ */
+ @Deprecated("use kotlin-analysis-api instead")
val bindingContext: BindingContext,
val diagnostics: List,
val regexCache: RegexCache,
diff --git a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinTree.kt b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinTree.kt
index 44c1a01cf..375c69fb2 100644
--- a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinTree.kt
+++ b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KotlinTree.kt
@@ -17,6 +17,7 @@
package org.sonarsource.kotlin.api.frontend
import com.intellij.openapi.editor.Document
+import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiErrorElement
import com.intellij.psi.PsiFile
@@ -33,6 +34,7 @@ class KotlinTree(
val bindingContext: BindingContext,
val diagnostics: List,
val regexCache: RegexCache,
+ val doResolve: Boolean,
)
data class KotlinSyntaxStructure(val ktFile: KtFile, val document: Document, val inputFile: InputFile) {
@@ -40,7 +42,13 @@ data class KotlinSyntaxStructure(val ktFile: KtFile, val document: Document, val
@JvmStatic
fun of(content: String, environment: Environment, inputFile: InputFile): KotlinSyntaxStructure {
- val psiFile: KtFile = environment.ktPsiFactory.createFile(inputFile.uri().path, normalizeEol(content))
+ val psiFile: KtFile = if (environment.k2session != null) {
+ val inputFilePath = FileUtil.toSystemIndependentName(inputFile.file().path)
+ environment.k2session!!.modulesWithFiles.values.first().find {
+ it.virtualFile.path == inputFilePath
+ } as KtFile
+ } else
+ environment.ktPsiFactory.createFile(inputFile.uri().path, normalizeEol(content))
val document = try {
psiFile.viewProvider.document ?: throw ParseException("Cannot extract document")
diff --git a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KtModuleProviderByCompilerConfiguration.java b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KtModuleProviderByCompilerConfiguration.java
new file mode 100644
index 000000000..2d8520b4b
--- /dev/null
+++ b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/frontend/KtModuleProviderByCompilerConfiguration.java
@@ -0,0 +1,51 @@
+/*
+ * SonarSource Kotlin
+ * Copyright (C) 2018-2024 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the Sonar Source-Available License for more details.
+ *
+ * You should have received a copy of the Sonar Source-Available License
+ * along with this program; if not, see https://sonarsource.com/license/ssal/
+ */
+package org.sonarsource.kotlin.api.frontend;
+
+import kotlin.jvm.functions.Function1;
+import org.jetbrains.kotlin.analysis.api.standalone.StandaloneAnalysisAPISessionBuilder;
+import org.jetbrains.kotlin.analysis.api.standalone.base.projectStructure.KotlinStaticProjectStructureProvider;
+import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment;
+import org.jetbrains.kotlin.config.CompilerConfiguration;
+import org.jetbrains.kotlin.psi.KtFile;
+
+import java.util.List;
+
+/**
+ * @deprecated use {@link StandaloneAnalysisAPISessionBuilder#buildKtModuleProvider(Function1)} instead
+ */
+@Deprecated(forRemoval = true)
+final class KtModuleProviderByCompilerConfiguration {
+
+ @SuppressWarnings("KotlinInternalInJava")
+ static KotlinStaticProjectStructureProvider build(
+ KotlinCoreProjectEnvironment kotlinCoreProjectEnvironment,
+ CompilerConfiguration compilerConfig,
+ List ktFiles
+ ) {
+ return org.jetbrains.kotlin.analysis.project.structure.impl
+ .KaModuleUtilsKt.buildKtModuleProviderByCompilerConfiguration(
+ kotlinCoreProjectEnvironment,
+ compilerConfig,
+ ktFiles
+ );
+ }
+
+ private KtModuleProviderByCompilerConfiguration() {
+ }
+
+}
diff --git a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/sensors/AbstractKotlinSensorExecuteContext.kt b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/sensors/AbstractKotlinSensorExecuteContext.kt
index 6ba830dd4..710e8684c 100644
--- a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/sensors/AbstractKotlinSensorExecuteContext.kt
+++ b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/sensors/AbstractKotlinSensorExecuteContext.kt
@@ -84,6 +84,8 @@ abstract class AbstractKotlinSensorExecuteContext(
abstract val bindingContext: BindingContext
+ abstract val doResolve: Boolean
+
fun analyzeFiles(): Boolean {
try {
val regexCache = RegexCache()
@@ -93,7 +95,7 @@ abstract class AbstractKotlinSensorExecuteContext(
}.forEach { (ktFile, doc, inputFile) ->
if (sensorContext.isCancelled) return false
val inputFileContext = InputFileContextImpl(sensorContext, inputFile, isInAndroidContext)
- val tree = KotlinTree(ktFile, doc, bindingContext, getFileDiagnostics(ktFile), regexCache)
+ val tree = KotlinTree(ktFile, doc, bindingContext, getFileDiagnostics(ktFile), regexCache, doResolve)
measureDuration(inputFile.filename()) {
analyzeFile(inputFileContext, tree)
diff --git a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/visiting/KotlinFileVisitor.kt b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/visiting/KotlinFileVisitor.kt
index fd828dad5..eda832e55 100644
--- a/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/visiting/KotlinFileVisitor.kt
+++ b/sonar-kotlin-api/src/main/java/org/sonarsource/kotlin/api/visiting/KotlinFileVisitor.kt
@@ -16,13 +16,48 @@
*/
package org.sonarsource.kotlin.api.visiting
+import org.jetbrains.kotlin.analysis.api.KaSession
+import org.jetbrains.kotlin.analysis.api.analyze
+import org.jetbrains.kotlin.psi.KtFile
import org.sonarsource.kotlin.api.checks.InputFileContext
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
import org.sonarsource.kotlin.api.frontend.KotlinTree
+/**
+ * Executes the given [action] in a [KaSession] context
+ * providing access to [Kotlin Analysis API](https://kotl.in/analysis-api).
+ */
+inline fun withKaSession(action: KaSession.() -> R): R = action(kaSession!!)
+
+@PublishedApi
+internal var kaSession: KaSession? = null
+
+/**
+ * Manages lifetime of [kaSession].
+ */
+internal inline fun kaSession(ktFile: KtFile, action: () -> Unit) {
+ check(kaSession == null)
+ try {
+ analyze(ktFile) {
+ kaSession = this
+ action()
+ }
+ } finally {
+ kaSession = null
+ }
+}
+
abstract class KotlinFileVisitor {
fun scan(fileContext: InputFileContext, root: KotlinTree) {
- visit(KotlinFileContext(fileContext, root.psiFile, root.bindingContext, root.diagnostics, root.regexCache))
+ val kotlinFileContext =
+ KotlinFileContext(fileContext, root.psiFile, root.bindingContext, root.diagnostics, root.regexCache)
+ if (root.doResolve) {
+ kaSession(root.psiFile) {
+ visit(kotlinFileContext)
+ }
+ } else {
+ visit(kotlinFileContext)
+ }
}
abstract fun visit(kotlinFileContext: KotlinFileContext)
diff --git a/sonar-kotlin-api/src/test/java/org/sonarsource/kotlin/api/frontend/KotlinCoreEnvironmentToolsTest.kt b/sonar-kotlin-api/src/test/java/org/sonarsource/kotlin/api/frontend/KotlinCoreEnvironmentToolsTest.kt
index e790c1d12..5c4b896f7 100644
--- a/sonar-kotlin-api/src/test/java/org/sonarsource/kotlin/api/frontend/KotlinCoreEnvironmentToolsTest.kt
+++ b/sonar-kotlin-api/src/test/java/org/sonarsource/kotlin/api/frontend/KotlinCoreEnvironmentToolsTest.kt
@@ -20,9 +20,16 @@ import org.assertj.core.api.Assertions.assertThat
import com.intellij.openapi.util.Disposer
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageVersion
+import org.jetbrains.kotlin.psi.KtIsExpression
+import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
+import org.jetbrains.kotlin.psi.KtFile
+import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
import org.jetbrains.kotlin.resolve.BindingContext
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
+import org.sonarsource.kotlin.api.visiting.kaSession
+import org.sonarsource.kotlin.api.visiting.withKaSession
+import java.io.File
class KotlinCoreEnvironmentToolsTest {
@@ -44,4 +51,63 @@ class KotlinCoreEnvironmentToolsTest {
.isNotEqualTo(BindingContext.EMPTY)
}
+ // https://kotlinlang.org/docs/whatsnew20.html#smart-cast-improvements
+ private val content = """
+ fun example(any: Any) {
+ val isString = any is String
+ if (isString) {
+ any.length
+ }
+ }
+ """.trimIndent()
+
+ /**
+ * @see k2
+ */
+ @Test
+ fun k1() {
+ val environment = Environment(
+ disposable,
+ listOf(),
+ LanguageVersion.LATEST_STABLE,
+ JvmTarget.JVM_1_8,
+ useK2 = false,
+ )
+ val ktFile = environment.ktPsiFactory.createFile("/fake.kt", content)
+ analyzeAndGetBindingContext(environment.env, listOf(ktFile))
+ kaSession(ktFile) {
+ withKaSession {
+ assertThat(ktFile.findDescendantOfType()!!.expressionType.toString())
+ .isEqualTo("kotlin/Boolean")
+ assertThat(ktFile.findDescendantOfType()!!.expressionType.toString())
+ .isEqualTo("kotlin/Unit")
+ }
+ }
+ }
+
+ /**
+ * @see k1
+ */
+ @Test
+ fun k2() {
+ val analysisSession = createK2AnalysisSession(
+ disposable,
+ compilerConfiguration(
+ listOf(),
+ LanguageVersion.LATEST_STABLE,
+ JvmTarget.JVM_1_8,
+ ),
+ listOf(KotlinVirtualFile(KotlinFileSystem(), File("/fake.kt"), content)),
+ )
+ val ktFile: KtFile = analysisSession.modulesWithFiles.entries.first().value[0] as KtFile
+ kaSession(ktFile) {
+ withKaSession {
+ assertThat(ktFile.findDescendantOfType()!!.expressionType.toString())
+ .isEqualTo("kotlin/Boolean")
+ assertThat(ktFile.findDescendantOfType()!!.expressionType.toString())
+ .isEqualTo("kotlin/Int")
+ }
+ }
+ }
+
}
diff --git a/sonar-kotlin-api/src/test/java/org/sonarsource/kotlin/api/sensors/AbstractKotlinSensorTest.kt b/sonar-kotlin-api/src/test/java/org/sonarsource/kotlin/api/sensors/AbstractKotlinSensorTest.kt
index 58144380b..2d89bdddd 100644
--- a/sonar-kotlin-api/src/test/java/org/sonarsource/kotlin/api/sensors/AbstractKotlinSensorTest.kt
+++ b/sonar-kotlin-api/src/test/java/org/sonarsource/kotlin/api/sensors/AbstractKotlinSensorTest.kt
@@ -195,6 +195,7 @@ class DummyKotlinSensor(checkFactory: CheckFactory, language: KotlinLanguage, ch
sensorContext, filesToAnalyze, progressReport, listOf(KtChecksVisitor(checks)), filenames, LOG
) {
override val bindingContext: BindingContext = BindingContext.EMPTY
+ override val doResolve: Boolean = false
}
override fun getFilesToAnalyse(sensorContext: SensorContext): Iterable =
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AnchorPrecedenceCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AnchorPrecedenceCheck.kt
index 7ddb22666..4ed3a2677 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AnchorPrecedenceCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AnchorPrecedenceCheck.kt
@@ -22,6 +22,7 @@ import org.sonarsource.analyzer.commons.regex.finders.AnchorPrecedenceFinder
import org.sonarsource.kotlin.api.regex.AbstractRegexCheck
import org.sonarsource.kotlin.api.regex.RegexContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5850")
class AnchorPrecedenceCheck : AbstractRegexCheck() {
override fun visitRegex(regex: RegexParseResult, regexContext: RegexContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AndroidBroadcastingCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AndroidBroadcastingCheck.kt
index 2db930561..57d727ae1 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AndroidBroadcastingCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AndroidBroadcastingCheck.kt
@@ -35,6 +35,7 @@ private val STICKY_BROADCAST_NAMES = setOf(
"sendStickyOrderedBroadcastAsUser",
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5320")
class AndroidBroadcastingCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ArrayHashCodeAndToStringCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ArrayHashCodeAndToStringCheck.kt
index b6b08db7d..1847ff695 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ArrayHashCodeAndToStringCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ArrayHashCodeAndToStringCheck.kt
@@ -52,6 +52,7 @@ private val PRIMITIVE_ARRAY_REPLACEMENT = mapOf("hashCode" to "contentHashCode",
private val OBJECT_ARRAY_REPLACEMENT = mapOf("hashCode" to "contentDeepHashCode", "toString" to "contentDeepToString")
private val ARRAY_OF_ARRAY_REPLACEMENT = mapOf("contentHashCode" to "contentDeepHashCode", "contentToString" to "contentDeepToString")
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2116")
class ArrayHashCodeAndToStringCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AuthorisingNonAuthenticatedUsersCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AuthorisingNonAuthenticatedUsersCheck.kt
index ae54ac6ab..2b45df348 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AuthorisingNonAuthenticatedUsersCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/AuthorisingNonAuthenticatedUsersCheck.kt
@@ -39,6 +39,7 @@ private val KEY_GEN_BUILDER_SET_AUTH_MATCHER = FunMatcher(qualifier = BUILDER, n
withArguments("kotlin.Boolean")
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6288")
class AuthorisingNonAuthenticatedUsersCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(KEY_GEN_BUILDER_BUILD_MATCHER)
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/BiometricAuthWithoutCryptoCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/BiometricAuthWithoutCryptoCheck.kt
index 2019c4457..d2290a471 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/BiometricAuthWithoutCryptoCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/BiometricAuthWithoutCryptoCheck.kt
@@ -33,6 +33,7 @@ private val ANDROIDX_AUTH = FunMatcher(qualifier = "androidx.biometric.Biometric
private const val MESSAGE = """Make sure performing a biometric authentication without a "CryptoObject" is safe here."""
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6293")
class BiometricAuthWithoutCryptoCheck : CallAbstractCheck() {
override val functionsToVisit = setOf(ANDROID_HARDWARE_AUTH, ANDROIDX_AUTH)
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CipherBlockChainingCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CipherBlockChainingCheck.kt
index 1d140b013..b122502e3 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CipherBlockChainingCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CipherBlockChainingCheck.kt
@@ -46,6 +46,7 @@ private val GET_INSTANCE_MATCHER = FunMatcher(qualifier = "javax.crypto.Cipher",
private val GET_BYTES_MATCHER = FunMatcher(qualifier = "kotlin.text", name = "toByteArray")
private val IV_PARAMETER_SPEC_MATCHER = ConstructorMatcher("javax.crypto.spec.IvParameterSpec")
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S3329")
class CipherBlockChainingCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(CIPHER_INIT_MATCHER)
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CipherModeOperationCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CipherModeOperationCheck.kt
index 70a6a89fc..cfa9bd1a7 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CipherModeOperationCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CipherModeOperationCheck.kt
@@ -44,6 +44,7 @@ private val GCM_PARAMETER_SPEC_MATCHER = ConstructorMatcher("javax.crypto.spec.G
private val GET_BYTES_MATCHER = FunMatcher(qualifier = "kotlin.text", name = "toByteArray")
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6432")
class CipherModeOperationCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(CIPHER_INIT_MATCHER)
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ClearTextProtocolCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ClearTextProtocolCheck.kt
index fb907c6ba..c4bd57fbd 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ClearTextProtocolCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ClearTextProtocolCheck.kt
@@ -60,6 +60,7 @@ private val ANDROID_SET_MIXED_CONTENT_MODE = FunMatcher(definingSupertype = "and
private fun msg(insecure: String, replaceWith: String) = "Using $insecure is insecure. Use $replaceWith instead."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5332")
class ClearTextProtocolCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionCallingItselfCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionCallingItselfCheck.kt
index f4c37e9dc..bc1e4ee05 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionCallingItselfCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionCallingItselfCheck.kt
@@ -35,6 +35,7 @@ private val COLLECTIONS_FUN_MATCHER = FunMatcher(definingSupertype = "kotlin.col
private const val MESSAGE = "Collections should not be passed as arguments to their own methods."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2114")
class CollectionCallingItselfCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(MUTABLE_COLLECTION_FUN_MATCHER, COLLECTIONS_FUN_MATCHER)
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionInappropriateCallsCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionInappropriateCallsCheck.kt
index 222e429f6..31918daf5 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionInappropriateCallsCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionInappropriateCallsCheck.kt
@@ -66,6 +66,7 @@ val funMatcherToArgumentIndexMap = mapOf(
const val ISSUE_MESSAGE = "This key/object cannot ever be present in the collection"
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2175")
class CollectionInappropriateCallsCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionShouldBeImmutableCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionShouldBeImmutableCheck.kt
index b574e1d0f..c2c83c7d4 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionShouldBeImmutableCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionShouldBeImmutableCheck.kt
@@ -67,6 +67,7 @@ private val mutableCollections =
"kotlin.collections.MutableCollection"
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6524")
class CollectionShouldBeImmutableCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionSizeAndArrayLengthCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionSizeAndArrayLengthCheck.kt
index 1317b1ef9..d8a5c27f8 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionSizeAndArrayLengthCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CollectionSizeAndArrayLengthCheck.kt
@@ -43,6 +43,7 @@ val ISSUE_MESSAGE_SIZE_NEVER_LT = """The size of an array/collection is never "<
val ISSUE_MESSAGE_SIZE_ALWAYS_GTEQ =
"""The size of an array/collection is always ">=0", update this test to either ".isNotEmpty()" or ".isEmpty()"."""
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S3981")
class CollectionSizeAndArrayLengthCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CoroutineScopeFunSuspendingCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CoroutineScopeFunSuspendingCheck.kt
index 176277c22..17de3876e 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CoroutineScopeFunSuspendingCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CoroutineScopeFunSuspendingCheck.kt
@@ -30,6 +30,7 @@ import org.sonarsource.kotlin.api.frontend.KotlinFileContext
private const val COROUTINE_SCOPE = "kotlinx.coroutines.CoroutineScope"
private const val MESSAGE = "Extension functions on CoroutineScope should not be suspending."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6312")
class CoroutineScopeFunSuspendingCheck : AbstractCheck() {
override fun visitNamedFunction(function: KtNamedFunction, kotlinFileContext: KotlinFileContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CoroutinesTimeoutApiUnusedCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CoroutinesTimeoutApiUnusedCheck.kt
index 7a5739bd0..43b03a509 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CoroutinesTimeoutApiUnusedCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/CoroutinesTimeoutApiUnusedCheck.kt
@@ -44,6 +44,7 @@ private val LAUNCH_ASYNC_MATCHER = FunMatcher(qualifier = KOTLINX_COROUTINES_PAC
withNames("launch", "async")
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6316")
class CoroutinesTimeoutApiUnusedCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(FunMatcher(definingSupertype = "$KOTLINX_COROUTINES_PACKAGE.Job", name = "cancel"))
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DataHashingCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DataHashingCheck.kt
index 6227e4e54..374f6c0bb 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DataHashingCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DataHashingCheck.kt
@@ -95,6 +95,7 @@ private val WEAK_METHOD_MATCHERS = listOf(
private val DEPRECATED_SPRING_PASSWORD_ENCODER_METHODS = DEPRECATED_SPRING_PASSWORD_ENCODERS.map(::ConstructorMatcher).toList() +
FunMatcher(qualifier = "org.springframework.security.crypto.password.NoOpPasswordEncoder", name = GET_INSTANCE)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S4790")
class DataHashingCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DebugFeatureEnabledCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DebugFeatureEnabledCheck.kt
index e1c13801b..3d3450bb7 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DebugFeatureEnabledCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DebugFeatureEnabledCheck.kt
@@ -27,6 +27,7 @@ import org.sonarsource.kotlin.api.frontend.KotlinFileContext
private const val MESSAGE = "Make sure this debug feature is deactivated before delivering the code in production."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S4507")
class DebugFeatureEnabledCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DelegationPatternCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DelegationPatternCheck.kt
index 0f746cb0d..0cfbd44a5 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DelegationPatternCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DelegationPatternCheck.kt
@@ -46,6 +46,7 @@ import org.sonarsource.kotlin.api.checks.returnType
import org.sonarsource.kotlin.api.checks.returnTypeAsString
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6514")
class DelegationPatternCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DeprecatedCodeCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DeprecatedCodeCheck.kt
index 704082b13..35ac9e41a 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DeprecatedCodeCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DeprecatedCodeCheck.kt
@@ -28,6 +28,7 @@ import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.checks.annotatedElement
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S1133")
class DeprecatedCodeCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DeprecatedCodeUsedCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DeprecatedCodeUsedCheck.kt
index 509cd341c..70676750b 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DeprecatedCodeUsedCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DeprecatedCodeUsedCheck.kt
@@ -27,6 +27,7 @@ import org.sonar.check.Rule
import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S1874")
class DeprecatedCodeUsedCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DuplicateBranchCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DuplicateBranchCheck.kt
index 624f0bad9..11de86612 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DuplicateBranchCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DuplicateBranchCheck.kt
@@ -26,6 +26,7 @@ import org.sonarsource.kotlin.api.reporting.SecondaryLocation
import org.sonarsource.kotlin.api.reporting.KotlinTextRanges.textRange
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S1871")
class DuplicateBranchCheck : AbstractBranchDuplication() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DuplicatesInCharacterClassCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DuplicatesInCharacterClassCheck.kt
index 30831dd4f..920c90393 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DuplicatesInCharacterClassCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/DuplicatesInCharacterClassCheck.kt
@@ -22,6 +22,7 @@ import org.sonarsource.analyzer.commons.regex.finders.DuplicatesInCharacterClass
import org.sonarsource.kotlin.api.regex.AbstractRegexCheck
import org.sonarsource.kotlin.api.regex.RegexContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5869")
class DuplicatesInCharacterClassCheck : AbstractRegexCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EmptyLineRegexCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EmptyLineRegexCheck.kt
index 5bfc2520e..9a03bc599 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EmptyLineRegexCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EmptyLineRegexCheck.kt
@@ -66,6 +66,7 @@ private val PATTERN_FIND = FunMatcher(qualifier = "java.util.regex.Matcher", nam
private val STRING_IS_EMPTY = FunMatcher(qualifier = KOTLIN_TEXT, name = "isEmpty")
private val REGEX_FIND = FunMatcher(qualifier = "kotlin.text.Regex", name = "find")
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5846")
class EmptyLineRegexCheck : AbstractRegexCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EmptyStringRepetitionCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EmptyStringRepetitionCheck.kt
index 779d4b4ee..286706a92 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EmptyStringRepetitionCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EmptyStringRepetitionCheck.kt
@@ -22,6 +22,7 @@ import org.sonarsource.analyzer.commons.regex.finders.EmptyStringRepetitionFinde
import org.sonarsource.kotlin.api.regex.AbstractRegexCheck
import org.sonarsource.kotlin.api.regex.RegexContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5842")
class EmptyStringRepetitionCheck : AbstractRegexCheck() {
override fun visitRegex(regex: RegexParseResult, regexContext: RegexContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EncryptionAlgorithmCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EncryptionAlgorithmCheck.kt
index acbcb469a..ca34095f4 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EncryptionAlgorithmCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EncryptionAlgorithmCheck.kt
@@ -33,6 +33,7 @@ val CIPHER_GET_INSTANCE_MATCHER = FunMatcher {
name = "getInstance"
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5542")
class EncryptionAlgorithmCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsArgumentTypeCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsArgumentTypeCheck.kt
index 6b6dbf706..0d6b26849 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsArgumentTypeCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsArgumentTypeCheck.kt
@@ -47,6 +47,7 @@ private val EQUALS_MATCHER = FunMatcher {
withArguments(ANY_TYPE)
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2097")
class EqualsArgumentTypeCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsMethodUsageCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsMethodUsageCheck.kt
index 255a761a5..e54b35b8e 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsMethodUsageCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsMethodUsageCheck.kt
@@ -33,6 +33,7 @@ import org.sonarsource.kotlin.api.reporting.SecondaryLocation
import org.sonarsource.kotlin.api.reporting.KotlinTextRanges.textRange
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6519")
class EqualsMethodUsageCheck : CallAbstractCheck() {
override val functionsToVisit = setOf(FunMatcher { name = EQUALS_METHOD_NAME; withArguments(ANY_TYPE) })
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsOverriddenWithArrayFieldCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsOverriddenWithArrayFieldCheck.kt
index b39958209..315671362 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsOverriddenWithArrayFieldCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsOverriddenWithArrayFieldCheck.kt
@@ -41,6 +41,7 @@ private val EXPECTED_OVERRIDES = listOf(
}
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6218")
class EqualsOverriddenWithArrayFieldCheck : AbstractCheck() {
override fun visitClass(klass: KtClass, context: KotlinFileContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsOverridenWithHashCodeCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsOverridenWithHashCodeCheck.kt
index 8f587aab6..724bbb75f 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsOverridenWithHashCodeCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/EqualsOverridenWithHashCodeCheck.kt
@@ -39,6 +39,7 @@ private val hashCodeMatcher = FunMatcher {
withNoArguments()
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S1206")
class EqualsOverridenWithHashCodeCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ExposedMutableFlowCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ExposedMutableFlowCheck.kt
index af25d1bbd..0f3deaba7 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ExposedMutableFlowCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ExposedMutableFlowCheck.kt
@@ -35,6 +35,7 @@ private val DISALLOWED_TYPES = listOf(
private const val MESSAGE = "Don't expose mutable flow types."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6305")
class ExposedMutableFlowCheck : AbstractCheck() {
override fun visitProperty(property: KtProperty, kotlinFileContext: KotlinFileContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ExternalAndroidStorageAccessCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ExternalAndroidStorageAccessCheck.kt
index 16d1a70e9..07e65ded8 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ExternalAndroidStorageAccessCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ExternalAndroidStorageAccessCheck.kt
@@ -58,6 +58,7 @@ private val HOTSPOT_PROPS = listOf(
"obbDirs",
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5324")
class ExternalAndroidStorageAccessCheck : CallAbstractCheck() {
override val functionsToVisit = HOTSPOT_FUNS
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/FinalFlowOperationCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/FinalFlowOperationCheck.kt
index 376cf130d..92d9456df 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/FinalFlowOperationCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/FinalFlowOperationCheck.kt
@@ -27,6 +27,7 @@ import org.sonarsource.kotlin.api.frontend.KotlinFileContext
private const val MESSAGE = "Unused coroutines Flow."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6314")
class FinalFlowOperationCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(FunMatcher(returnType = COROUTINES_FLOW))
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/FlowChannelReturningFunsNotSuspendingCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/FlowChannelReturningFunsNotSuspendingCheck.kt
index 4d2df5bc0..6ecfaa1be 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/FlowChannelReturningFunsNotSuspendingCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/FlowChannelReturningFunsNotSuspendingCheck.kt
@@ -30,6 +30,7 @@ import org.sonarsource.kotlin.api.frontend.KotlinFileContext
private val FORBIDDEN_RETURN_TYPES = listOf(COROUTINES_FLOW, COROUTINES_CHANNEL)
private const val MESSAGE = """Functions returning "Flow" or "Channel" should not be suspending"""
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6309")
class FlowChannelReturningFunsNotSuspendingCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/GraphemeClustersInClassesCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/GraphemeClustersInClassesCheck.kt
index eb2ad1c07..23bd456a7 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/GraphemeClustersInClassesCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/GraphemeClustersInClassesCheck.kt
@@ -22,6 +22,7 @@ import org.sonarsource.analyzer.commons.regex.finders.GraphemeInClassFinder
import org.sonarsource.kotlin.api.regex.AbstractRegexCheck
import org.sonarsource.kotlin.api.regex.RegexContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5868")
class GraphemeClustersInClassesCheck : AbstractRegexCheck() {
override fun visitRegex(regex: RegexParseResult, regexContext: RegexContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IgnoredOperationStatusCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IgnoredOperationStatusCheck.kt
index 3c543f99a..c520056f9 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IgnoredOperationStatusCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IgnoredOperationStatusCheck.kt
@@ -25,6 +25,7 @@ import org.sonarsource.kotlin.api.checks.FunMatcher
import org.sonarsource.kotlin.api.checks.simpleName
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S899")
class IgnoredOperationStatusCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IndexedAccessCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IndexedAccessCheck.kt
index 4a2eb4d75..ad1a66792 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IndexedAccessCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IndexedAccessCheck.kt
@@ -26,6 +26,7 @@ import org.sonarsource.kotlin.api.checks.FunMatcher
import org.sonarsource.kotlin.api.checks.FunMatcherImpl
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6518")
class IndexedAccessCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InjectableDispatchersCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InjectableDispatchersCheck.kt
index 0e20fb0e5..9a4fd7772 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InjectableDispatchersCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InjectableDispatchersCheck.kt
@@ -33,6 +33,7 @@ import org.sonarsource.kotlin.api.frontend.secondaryOf
private const val MESSAGE = "Avoid hardcoded dispatchers."
private const val DISPATCHERS_OBJECT = "$KOTLINX_COROUTINES_PACKAGE.Dispatchers"
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6310")
class InjectableDispatchersCheck : CallAbstractCheck() {
override val functionsToVisit = FUNS_ACCEPTING_DISPATCHERS
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InterfaceCouldBeFunctionalCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InterfaceCouldBeFunctionalCheck.kt
index f24a39b22..0ca3392db 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InterfaceCouldBeFunctionalCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InterfaceCouldBeFunctionalCheck.kt
@@ -26,6 +26,7 @@ import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.checks.getType
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6517")
class InterfaceCouldBeFunctionalCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InvalidRegexCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InvalidRegexCheck.kt
index a0fce121e..0a2599a21 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InvalidRegexCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/InvalidRegexCheck.kt
@@ -27,6 +27,7 @@ import org.sonarsource.kotlin.api.frontend.KotlinFileContext
private const val MESSAGE_MULTIPLE_ERRORS = "Fix the syntax errors inside this regex."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5856")
class InvalidRegexCheck : AbstractRegexCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IsInstanceMethodCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IsInstanceMethodCheck.kt
index 8dad42147..c477245e9 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IsInstanceMethodCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/IsInstanceMethodCheck.kt
@@ -35,6 +35,7 @@ import org.sonarsource.kotlin.api.frontend.KotlinFileContext
private val JAVA_CLASS_KEYWORDS = listOf("java", "javaClass")
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6202")
class IsInstanceMethodCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/LiftReturnStatementCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/LiftReturnStatementCheck.kt
index a1aee3688..a0e518e7f 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/LiftReturnStatementCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/LiftReturnStatementCheck.kt
@@ -27,6 +27,7 @@ import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.checks.isExhaustive
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6510")
class LiftReturnStatementCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MainSafeCoroutinesCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MainSafeCoroutinesCheck.kt
index 88355946c..c8913883c 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MainSafeCoroutinesCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MainSafeCoroutinesCheck.kt
@@ -67,6 +67,7 @@ val BLOCKING_ANNOTATIONS = setOf(
"javax.net.ssl.SSLException",
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6307")
class MainSafeCoroutinesCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MapValuesShouldBeAccessedSafelyCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MapValuesShouldBeAccessedSafelyCheck.kt
index 9c1ed66c6..983ebd7f4 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MapValuesShouldBeAccessedSafelyCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MapValuesShouldBeAccessedSafelyCheck.kt
@@ -33,6 +33,7 @@ import org.sonarsource.kotlin.api.reporting.message
import org.sonarsource.kotlin.api.checks.determineType
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6611")
class MapValuesShouldBeAccessedSafelyCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MobileDatabaseEncryptionKeysCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MobileDatabaseEncryptionKeysCheck.kt
index 917b77c97..ff80b0d5b 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MobileDatabaseEncryptionKeysCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/MobileDatabaseEncryptionKeysCheck.kt
@@ -45,6 +45,7 @@ private const val ENCRYPTION_KEY = "encryptionKey"
private const val CHANGE_PASSWORD = "changePassword"
private val CREATE_CHAR_BYTE_ARRAY = FunMatcher(qualifier = "kotlin") { withNames("byteArrayOf", "charArrayOf") }
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6301")
class MobileDatabaseEncryptionKeysCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PreparedStatementAndResultSetCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PreparedStatementAndResultSetCheck.kt
index dfadb6416..e3cc890ad 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PreparedStatementAndResultSetCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PreparedStatementAndResultSetCheck.kt
@@ -44,6 +44,7 @@ private val RESULT_SET_GET = FunMatcher(qualifier = "java.sql.ResultSet", nameRe
withArguments(ArgumentMatcher(INT_TYPE), ArgumentMatcher.ANY)
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2695")
class PreparedStatementAndResultSetCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PropertyGetterAndSetterUsageCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PropertyGetterAndSetterUsageCheck.kt
index b7d0f0ed3..da105a7f1 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PropertyGetterAndSetterUsageCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PropertyGetterAndSetterUsageCheck.kt
@@ -41,6 +41,7 @@ import org.sonarsource.kotlin.api.frontend.secondaryOf
private val GETTER_PREFIX = Regex("""^(get|is)\p{javaUpperCase}""")
private val SETTER_PREFIX = Regex("""^set\p{javaUpperCase}""")
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6512")
class PropertyGetterAndSetterUsageCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PseudoRandomCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PseudoRandomCheck.kt
index 261a4687a..fb82c0c05 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PseudoRandomCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/PseudoRandomCheck.kt
@@ -47,6 +47,7 @@ private val RANDOM_CONSTRUCTOR_TYPES = setOf(
"org.apache.commons.lang.math.JVMRandom"
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2245")
class PseudoRandomCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReasonableTypeCastsCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReasonableTypeCastsCheck.kt
index d25c9551c..21aa21cc9 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReasonableTypeCastsCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReasonableTypeCastsCheck.kt
@@ -22,6 +22,7 @@ import org.sonar.check.Rule
import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6530")
class ReasonableTypeCastsCheck : AbstractCheck() {
override fun visitKtFile(file: KtFile, context: KotlinFileContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReceivingIntentsCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReceivingIntentsCheck.kt
index 6feb431e3..0e3242b18 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReceivingIntentsCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReceivingIntentsCheck.kt
@@ -24,6 +24,7 @@ import org.sonarsource.kotlin.api.checks.FunMatcher
import org.sonarsource.kotlin.api.checks.isNull
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5322")
class ReceivingIntentsCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantMethodsInDataClassesCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantMethodsInDataClassesCheck.kt
index 194065d24..1a9934251 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantMethodsInDataClassesCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantMethodsInDataClassesCheck.kt
@@ -52,6 +52,7 @@ private val HASHCODE_MATCHER = FunMatcher {
private val OBJECTS_HASH_MATCHER = FunMatcher(qualifier = "java.util.Objects", name = "hash")
private val ARRAYS_HASHCODE_MATCHER = FunMatcher(qualifier = "java.util.Arrays", name = "hashCode")
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6207")
class RedundantMethodsInDataClassesCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantSuspendModifierCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantSuspendModifierCheck.kt
index d7b4be0cd..809be533e 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantSuspendModifierCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantSuspendModifierCheck.kt
@@ -27,6 +27,7 @@ import org.sonarsource.kotlin.api.checks.overrides
import org.sonarsource.kotlin.api.checks.suspendModifier
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6318")
class RedundantSuspendModifierCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantTypeCastsCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantTypeCastsCheck.kt
index 56a51fe8a..15f020bf6 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantTypeCastsCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RedundantTypeCastsCheck.kt
@@ -24,6 +24,7 @@ import org.sonarsource.kotlin.api.reporting.Message
import org.sonarsource.kotlin.api.reporting.message
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6531")
class RedundantTypeCastsCheck : AbstractCheck() {
override fun visitKtFile(file: KtFile, context: KotlinFileContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RegexComplexityCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RegexComplexityCheck.kt
index 4eb7695be..0acca9873 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RegexComplexityCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RegexComplexityCheck.kt
@@ -25,6 +25,7 @@ import org.sonarsource.kotlin.api.regex.RegexContext
private const val DEFAULT_MAX = 20
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5843")
class RegexComplexityCheck : AbstractRegexCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReluctantQuantifierCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReluctantQuantifierCheck.kt
index d0144c380..2108255b0 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReluctantQuantifierCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReluctantQuantifierCheck.kt
@@ -22,6 +22,7 @@ import org.sonarsource.analyzer.commons.regex.finders.ReluctantQuantifierFinder
import org.sonarsource.kotlin.api.regex.AbstractRegexCheck
import org.sonarsource.kotlin.api.regex.RegexContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5857")
class ReluctantQuantifierCheck : AbstractRegexCheck() {
override fun visitRegex(regex: RegexParseResult, regexContext: RegexContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReplaceGuavaWithKotlinCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReplaceGuavaWithKotlinCheck.kt
index f2125bbd6..136add58f 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReplaceGuavaWithKotlinCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ReplaceGuavaWithKotlinCheck.kt
@@ -72,6 +72,7 @@ private val REPLACEMENT_TYPES = mapOf(
GUAVA_OPTIONAL to """Use "java.util.Optional" instead.""",
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S4738")
class ReplaceGuavaWithKotlinCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RobustCryptographicKeysCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RobustCryptographicKeysCheck.kt
index 4e91e8ef5..b54b44a1a 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RobustCryptographicKeysCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RobustCryptographicKeysCheck.kt
@@ -72,6 +72,7 @@ private val INSECURE_EC_SPECS = setOf(
)
private const val EC_MIN_KEY_SIZE = 224
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S4426")
class RobustCryptographicKeysCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RunFinalizersCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RunFinalizersCheck.kt
index 3269b9409..c00c87b94 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RunFinalizersCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/RunFinalizersCheck.kt
@@ -23,6 +23,7 @@ import org.sonarsource.kotlin.api.checks.CallAbstractCheck
import org.sonarsource.kotlin.api.checks.FunMatcher
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2151")
class RunFinalizersCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SamConversionCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SamConversionCheck.kt
index 5e691a6ba..0e8677ecd 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SamConversionCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SamConversionCheck.kt
@@ -25,6 +25,7 @@ import org.sonarsource.kotlin.api.checks.isFunctionalInterface
import org.sonarsource.kotlin.api.checks.merge
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6516")
class SamConversionCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ScheduledThreadPoolExecutorZeroCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ScheduledThreadPoolExecutorZeroCheck.kt
index 4c7584bc8..5fe5e0072 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ScheduledThreadPoolExecutorZeroCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ScheduledThreadPoolExecutorZeroCheck.kt
@@ -39,6 +39,7 @@ private val THREAD_POOL_CONSTRUCTOR_MATCHER =
private val POOL_SIZE_SETTER_MATCHER =
FunMatcher(definingSupertype = "java.util.concurrent.ThreadPoolExecutor", name = "setCorePoolSize") { withArguments("kotlin.Int") }
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2122")
class ScheduledThreadPoolExecutorZeroCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ServerCertificateCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ServerCertificateCheck.kt
index 3bc73e349..36d6c0b72 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ServerCertificateCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ServerCertificateCheck.kt
@@ -44,6 +44,7 @@ private val funMatchers = listOf(
})
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S4830")
class ServerCertificateCheck : AbstractCheck() {
override fun visitNamedFunction(function: KtNamedFunction, kotlinFileContext: KotlinFileContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifiedPreconditionsCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifiedPreconditionsCheck.kt
index 760b838c3..8a9185dc8 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifiedPreconditionsCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifiedPreconditionsCheck.kt
@@ -52,6 +52,7 @@ private val ILLEGAL_ARGUMENT_EXCEPTION_CONSTRUCTOR_MATCH = ConstructorMatcher(ty
withArguments("kotlin.String")
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6532")
class SimplifiedPreconditionsCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifyFilteringBeforeTerminalOperationCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifyFilteringBeforeTerminalOperationCheck.kt
index e0f8793b6..2d7433932 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifyFilteringBeforeTerminalOperationCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifyFilteringBeforeTerminalOperationCheck.kt
@@ -29,6 +29,7 @@ import org.sonarsource.kotlin.api.reporting.message
private const val KOTLIN_COLLECTIONS_QUALIFIER = "kotlin.collections"
private val FILTER_MATCHER = FunMatcher(qualifier = KOTLIN_COLLECTIONS_QUALIFIER, name = "filter") { withArguments("kotlin.Function1") }
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6527")
class SimplifyFilteringBeforeTerminalOperationCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifySizeExpressionCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifySizeExpressionCheck.kt
index 334a912fd..9e9605854 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifySizeExpressionCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SimplifySizeExpressionCheck.kt
@@ -79,6 +79,7 @@ private val lengthFieldMatcher = FieldMatcher {
withQualifiers("kotlin.String")
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6529")
class SimplifySizeExpressionCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SingletonPatternCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SingletonPatternCheck.kt
index 9f5c136c3..32e779131 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SingletonPatternCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SingletonPatternCheck.kt
@@ -46,6 +46,7 @@ private val lazyInitializationMatcher = FunMatcher(
definingSupertype = "kotlin"
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6515")
class SingletonPatternCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StreamNotConsumedCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StreamNotConsumedCheck.kt
index ab16380ab..0bcb3c43a 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StreamNotConsumedCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StreamNotConsumedCheck.kt
@@ -44,6 +44,7 @@ private val SEQUENCE_MATCHER = FunMatcher(qualifier = "kotlin.sequences") {
)
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S3958")
class StreamNotConsumedCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StrongCipherAlgorithmCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StrongCipherAlgorithmCheck.kt
index b8240b7da..6807559a4 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StrongCipherAlgorithmCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StrongCipherAlgorithmCheck.kt
@@ -39,6 +39,7 @@ private const val msg = "Use a strong cipher algorithm."
private val cipherGetInstanceMatcher = FunMatcher(qualifier = "javax.crypto.Cipher", name = "getInstance")
private val nullCipherConstructorMatcher = ConstructorMatcher("javax.crypto.NullCipher")
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5547")
class StrongCipherAlgorithmCheck : AbstractCheck() {
override fun visitCallExpression(callExpr: KtCallExpression, kotlinFileContext: KotlinFileContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StructuredConcurrencyPrinciplesCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StructuredConcurrencyPrinciplesCheck.kt
index c9aa001dc..6d97de775 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StructuredConcurrencyPrinciplesCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/StructuredConcurrencyPrinciplesCheck.kt
@@ -42,6 +42,7 @@ private val SUPERVISOR_JOB_CONSTRUCTOR = FunMatcher(qualifier = KOTLINX_COROUTIN
private const val MESSAGE_ENDING = " here leads to the breaking of structured concurrency principles."
private const val DELICATE_API_CLASS_TYPE = "kotlin.reflect.KClass"
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6306")
class StructuredConcurrencyPrinciplesCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SuspendingFunCallerDispatcherCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SuspendingFunCallerDispatcherCheck.kt
index ac8d415c7..a43608ff8 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SuspendingFunCallerDispatcherCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/SuspendingFunCallerDispatcherCheck.kt
@@ -27,6 +27,7 @@ import org.sonarsource.kotlin.api.checks.CallAbstractCheck
import org.sonarsource.kotlin.api.checks.FUNS_ACCEPTING_DISPATCHERS
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6311")
class SuspendingFunCallerDispatcherCheck : CallAbstractCheck() {
override val functionsToVisit = FUNS_ACCEPTING_DISPATCHERS
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnencryptedDatabaseOnMobileCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnencryptedDatabaseOnMobileCheck.kt
index 55b090698..46ad849ec 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnencryptedDatabaseOnMobileCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnencryptedDatabaseOnMobileCheck.kt
@@ -38,6 +38,7 @@ private val REALM_ENC_KEY_FUN = FunMatcher(definingSupertype = "io.realm.RealmCo
private const val MESSAGE = "Make sure using an unencrypted database is safe here."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6291")
class UnencryptedDatabaseOnMobileCheck : AbstractCheck() {
override fun visitCallExpression(callExpression: KtCallExpression, kotlinFileContext: KotlinFileContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnencryptedFilesInMobileApplicationsCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnencryptedFilesInMobileApplicationsCheck.kt
index 80618d8e7..b0b05087e 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnencryptedFilesInMobileApplicationsCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnencryptedFilesInMobileApplicationsCheck.kt
@@ -26,6 +26,7 @@ import org.sonarsource.kotlin.api.frontend.KotlinFileContext
private const val MESSAGE = "Make sure using unencrypted files is safe here."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6300")
class UnencryptedFilesInMobileApplicationsCheck : CallAbstractCheck() {
override val functionsToVisit = setOf(
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnicodeAwareCharClassesCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnicodeAwareCharClassesCheck.kt
index 9681bfe4d..5de6a08e3 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnicodeAwareCharClassesCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnicodeAwareCharClassesCheck.kt
@@ -26,6 +26,7 @@ import org.sonarsource.kotlin.api.regex.PATTERN_COMPILE_MATCHER
import org.sonarsource.kotlin.api.regex.RegexContext
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5867")
class UnicodeAwareCharClassesCheck : AbstractRegexCheck() {
override fun visitRegex(
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnnecessaryImportsCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnnecessaryImportsCheck.kt
index 0debea09f..a72ca4424 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnnecessaryImportsCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnnecessaryImportsCheck.kt
@@ -54,6 +54,7 @@ private const val MESSAGE_REDUNDANT = "Remove this redundant import."
private val DELEGATES_IMPORTED_NAMES = setOf("getValue", "setValue", "provideDelegate")
private val ARRAY_ACCESS_IMPORTED_NAMES = setOf("get", "set")
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S1128")
class UnnecessaryImportsCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableHashSaltCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableHashSaltCheck.kt
index 279cfc6ac..103a27bf2 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableHashSaltCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableHashSaltCheck.kt
@@ -49,6 +49,7 @@ private val matcherSaltIndexMap = mapOf(
ConstructorMatcher("$SPECS_PACKAGE.$PARAMETER_SPEC_FUN_NAME") to 0,
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2053")
class UnpredictableHashSaltCheck : CallAbstractCheck() {
override val functionsToVisit = matcherSaltIndexMap.keys
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableSecureRandomSaltCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableSecureRandomSaltCheck.kt
index 89cc0cb07..37da051b6 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableSecureRandomSaltCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnpredictableSecureRandomSaltCheck.kt
@@ -37,6 +37,7 @@ import org.sonarsource.kotlin.api.frontend.KotlinFileContext
private const val MESSAGE = "Change this seed value to something unpredictable, or remove the seed."
private const val SECURE_RANDOM = "java.security.SecureRandom"
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S4347")
class UnpredictableSecureRandomSaltCheck : CallAbstractCheck() {
override val functionsToVisit = listOf(
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnsuitedFindFunctionWithNullComparisonCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnsuitedFindFunctionWithNullComparisonCheck.kt
index 6dc613795..e5c6dcf4a 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnsuitedFindFunctionWithNullComparisonCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnsuitedFindFunctionWithNullComparisonCheck.kt
@@ -42,6 +42,7 @@ import org.sonarsource.kotlin.api.reporting.message
*
* The rule suggests to replace the pattern with `any(predicate)`, `none(predicate)`, and `contains(element)` depending on the case.
*/
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6528")
class UnsuitedFindFunctionWithNullComparisonCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedDeferredResultCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedDeferredResultCheck.kt
index c19251852..051a9c108 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedDeferredResultCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedDeferredResultCheck.kt
@@ -24,6 +24,7 @@ import org.sonarsource.kotlin.api.checks.DEFERRED_FQN
import org.sonarsource.kotlin.api.checks.expressionTypeFqn
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6315")
class UnusedDeferredResultCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedLocalVariableCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedLocalVariableCheck.kt
index cd09f0366..051d9ed9d 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedLocalVariableCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedLocalVariableCheck.kt
@@ -25,6 +25,7 @@ import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.checks.getVariableType
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S1481")
class UnusedLocalVariableCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedPrivateMethodCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedPrivateMethodCheck.kt
index 2d3981011..d7f2c6eff 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedPrivateMethodCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UnusedPrivateMethodCheck.kt
@@ -46,6 +46,7 @@ private val COMMON_ANNOTATIONS = listOf(
"kotlin.jvm.Throws",
)
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S1144")
class UnusedPrivateMethodCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessAssignmentsCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessAssignmentsCheck.kt
index c055857ae..8a2905028 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessAssignmentsCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessAssignmentsCheck.kt
@@ -23,6 +23,7 @@ import org.sonar.check.Rule
import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6615")
class UselessAssignmentsCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessIncrementCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessIncrementCheck.kt
index ba7e0adb2..8a67b1ab1 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessIncrementCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessIncrementCheck.kt
@@ -30,6 +30,7 @@ import org.sonarsource.kotlin.api.frontend.KotlinFileContext
private val POSTFIX_INCREMENT_OPERATORS = listOf(KtTokens.PLUSPLUS, KtTokens.MINUSMINUS)
private const val MESSAGE = "Remove this increment or correct the code not to waste it."
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S2123")
class UselessIncrementCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessNullCheckCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessNullCheckCheck.kt
index 5940ef517..b6f00fd5d 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessNullCheckCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/UselessNullCheckCheck.kt
@@ -46,6 +46,7 @@ private val NON_NULL_CHECK_FUNS = FunMatcher("kotlin") {
withNames("requireNotNull", "checkNotNull")
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6619")
class UselessNullCheckCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VarShouldBeValCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VarShouldBeValCheck.kt
index 02c1e2df0..ace6f525b 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VarShouldBeValCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VarShouldBeValCheck.kt
@@ -40,6 +40,7 @@ import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
import org.sonarsource.kotlin.api.reporting.message
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S3353")
class VarShouldBeValCheck : AbstractCheck() {
override fun visitKtFile(file: KtFile, data: KotlinFileContext) {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VerifiedServerHostnamesCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VerifiedServerHostnamesCheck.kt
index 3c00b9151..04db7729c 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VerifiedServerHostnamesCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VerifiedServerHostnamesCheck.kt
@@ -28,6 +28,7 @@ import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.checks.FunMatcher
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S5527")
class VerifiedServerHostnamesCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ViewModelSuspendingFunctionsCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ViewModelSuspendingFunctionsCheck.kt
index 10179c08f..30a0ef390 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ViewModelSuspendingFunctionsCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/ViewModelSuspendingFunctionsCheck.kt
@@ -28,6 +28,7 @@ import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.api.checks.suspendModifier
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6313")
class ViewModelSuspendingFunctionsCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VoidShouldBeUnitCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VoidShouldBeUnitCheck.kt
index 7fe77c3f8..5cc419924 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VoidShouldBeUnitCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/VoidShouldBeUnitCheck.kt
@@ -43,6 +43,7 @@ private val message = message {
+"."
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6508")
class VoidShouldBeUnitCheck : AbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WeakSSLContextCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WeakSSLContextCheck.kt
index 9da68bc9a..34d7e4072 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WeakSSLContextCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WeakSSLContextCheck.kt
@@ -32,6 +32,7 @@ import org.sonarsource.kotlin.api.reporting.SecondaryLocation
import org.sonarsource.kotlin.api.reporting.KotlinTextRanges.textRange
import org.sonarsource.kotlin.api.frontend.KotlinFileContext
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S4423")
class WeakSSLContextCheck : AbstractCheck() {
private val WEAK_FOR_OK_HTTP = setOf(
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewJavaScriptSupportCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewJavaScriptSupportCheck.kt
index f60d12e8d..9e95210c3 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewJavaScriptSupportCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewJavaScriptSupportCheck.kt
@@ -34,6 +34,7 @@ private const val MESSAGE = "Make sure that enabling JavaScript support is safe
private val ANDROID_SET_JAVASCRIPT_ENABLED =
FunMatcher(definingSupertype = "android.webkit.WebSettings", name = "setJavaScriptEnabled") { withArguments("kotlin.Boolean") }
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6362")
class WebViewJavaScriptSupportCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewsFileAccessCheck.kt b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewsFileAccessCheck.kt
index b37e921f7..9f2436c78 100644
--- a/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewsFileAccessCheck.kt
+++ b/sonar-kotlin-checks/src/main/java/org/sonarsource/kotlin/checks/WebViewsFileAccessCheck.kt
@@ -49,6 +49,7 @@ private val ANDROID_FILE_ACCESS_MATCHER = FunMatcher(definingSupertype = "androi
withArguments("kotlin.Boolean")
}
+@org.sonarsource.kotlin.api.frontend.K1only
@Rule(key = "S6363")
class WebViewsFileAccessCheck : CallAbstractCheck() {
diff --git a/sonar-kotlin-checks/src/test/java/org/sonarsource/kotlin/checks/CheckTest.kt b/sonar-kotlin-checks/src/test/java/org/sonarsource/kotlin/checks/CheckTest.kt
index 529c758a5..337cb2c39 100644
--- a/sonar-kotlin-checks/src/test/java/org/sonarsource/kotlin/checks/CheckTest.kt
+++ b/sonar-kotlin-checks/src/test/java/org/sonarsource/kotlin/checks/CheckTest.kt
@@ -17,8 +17,10 @@
package org.sonarsource.kotlin.checks
import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.condition.DisabledIf
import org.sonarsource.kotlin.api.checks.AbstractCheck
import org.sonarsource.kotlin.testapi.KotlinVerifier
+import kotlin.reflect.full.hasAnnotation
private const val TEST_FILE_POSTFIX = "Sample.kt"
@@ -31,8 +33,22 @@ abstract class CheckTest(
) {
protected val checkName = check::class.java.simpleName
+ private fun k1only() = check::class.hasAnnotation()
+
+ @Test
+ @DisabledIf("k1only")
+ fun `with k2 semantics`() {
+ KotlinVerifier(check) {
+ this.useK2 = true
+ this.fileName = sampleFileSemantics ?: "$checkName$TEST_FILE_POSTFIX"
+ this@CheckTest.classpath?.let { this.classpath = it }
+ this@CheckTest.dependencies?.let { this.deps = it }
+ this.isAndroid = this@CheckTest.isAndroid
+ }.verify()
+ }
+
@Test
- fun `with semantics`() {
+ fun `with k1 semantics`() {
KotlinVerifier(check) {
this.fileName = sampleFileSemantics ?: "$checkName$TEST_FILE_POSTFIX"
this@CheckTest.classpath?.let { this.classpath = it }
diff --git a/sonar-kotlin-gradle/src/main/java/org/sonarsource/kotlin/gradle/KotlinGradleSensor.kt b/sonar-kotlin-gradle/src/main/java/org/sonarsource/kotlin/gradle/KotlinGradleSensor.kt
index 0367c9270..23ddca763 100644
--- a/sonar-kotlin-gradle/src/main/java/org/sonarsource/kotlin/gradle/KotlinGradleSensor.kt
+++ b/sonar-kotlin-gradle/src/main/java/org/sonarsource/kotlin/gradle/KotlinGradleSensor.kt
@@ -59,6 +59,7 @@ class KotlinGradleSensor(
sensorContext, filesToAnalyze, progressReport, listOf(KtChecksVisitor(checks)), filenames, LOG
) {
override val bindingContext: BindingContext = BindingContext.EMPTY
+ override val doResolve: Boolean = false
}
override fun getFilesToAnalyse(sensorContext: SensorContext): Iterable {
diff --git a/sonar-kotlin-plugin/build.gradle.kts b/sonar-kotlin-plugin/build.gradle.kts
index 82b00df9b..b9703ce15 100644
--- a/sonar-kotlin-plugin/build.gradle.kts
+++ b/sonar-kotlin-plugin/build.gradle.kts
@@ -96,8 +96,14 @@ tasks.shadowJar {
exclude("META-INF/native/**/*jansi*")
exclude("org/jline/**")
exclude("net/jpountz/**")
+ dependencies {
+ // include only K1, and exclude K2 for the time being
+ exclude(dependency("org.jetbrains.kotlin:analysis-api-k2-for-ide"))
+ exclude(dependency("org.jetbrains.kotlin:low-level-api-fir-for-ide"))
+ exclude(dependency("org.jetbrains.kotlin:symbol-light-classes-for-ide"))
+ }
doLast {
- enforceJarSizeAndCheckContent(shadowJar.get().archiveFile.get().asFile, 37_500_000L, 38_000_000L)
+ enforceJarSizeAndCheckContent(shadowJar.get().archiveFile.get().asFile, 45_800_000L, 46_200_000L)
}
}
diff --git a/sonar-kotlin-plugin/src/main/java/org/sonarsource/kotlin/plugin/KotlinSensor.kt b/sonar-kotlin-plugin/src/main/java/org/sonarsource/kotlin/plugin/KotlinSensor.kt
index c3f3210b2..c78e192d2 100644
--- a/sonar-kotlin-plugin/src/main/java/org/sonarsource/kotlin/plugin/KotlinSensor.kt
+++ b/sonar-kotlin-plugin/src/main/java/org/sonarsource/kotlin/plugin/KotlinSensor.kt
@@ -85,6 +85,8 @@ class KotlinSensor(
BindingContext.EMPTY
}
}
+
+ override val doResolve: Boolean = true
}
private fun visitors(sensorContext: SensorContext): List =
diff --git a/sonar-kotlin-plugin/src/main/java/org/sonarsource/kotlin/plugin/linking/WorkaroundForJarMinimization.java b/sonar-kotlin-plugin/src/main/java/org/sonarsource/kotlin/plugin/linking/WorkaroundForJarMinimization.java
index 939e9fb72..ed9bfb37f 100644
--- a/sonar-kotlin-plugin/src/main/java/org/sonarsource/kotlin/plugin/linking/WorkaroundForJarMinimization.java
+++ b/sonar-kotlin-plugin/src/main/java/org/sonarsource/kotlin/plugin/linking/WorkaroundForJarMinimization.java
@@ -35,6 +35,18 @@ public class WorkaroundForJarMinimization {
/** META-INF/services/org.jetbrains.kotlin.resolve.jvm.jvmSignature.KotlinToJvmSignatureMapper */
org.jetbrains.kotlin.codegen.signature.KotlinToJvmSignatureMapperImpl.class,
+ // META-INF/analysis-api/analysis-api-impl-base.xml
+ org.jetbrains.kotlin.analysis.api.impl.base.java.source.JavaElementSourceWithSmartPointerFactory.class,
+ org.jetbrains.kotlin.analysis.api.impl.base.references.HLApiReferenceProviderService.class,
+ org.jetbrains.kotlin.analysis.api.impl.base.projectStructure.KaBaseModuleProvider.class,
+ org.jetbrains.kotlin.analysis.api.platform.KotlinProjectMessageBusProvider.class,
+ org.jetbrains.kotlin.analysis.api.impl.base.permissions.KaBaseAnalysisPermissionChecker.class,
+ org.jetbrains.kotlin.analysis.api.impl.base.lifetime.KaBaseLifetimeTracker.class,
+ // META-INF/analysis-api/analysis-api-fe10.xml
+ org.jetbrains.kotlin.analysis.api.descriptors.KaFe10SessionProvider.class,
+ org.jetbrains.kotlin.references.fe10.base.KtFe10KotlinReferenceProviderContributor.class,
+ org.jetbrains.kotlin.analysis.api.descriptors.references.ReadWriteAccessCheckerDescriptorsImpl.class,
+
/** Used to have proper named groups behavior in regular expressions */
kotlin.internal.jdk8.JDK8PlatformImplementations.class
);
diff --git a/sonar-kotlin-plugin/src/test/java/org/sonarsource/kotlin/plugin/KotlinSensorTest.kt b/sonar-kotlin-plugin/src/test/java/org/sonarsource/kotlin/plugin/KotlinSensorTest.kt
index 78b0e6c27..3622534f8 100644
--- a/sonar-kotlin-plugin/src/test/java/org/sonarsource/kotlin/plugin/KotlinSensorTest.kt
+++ b/sonar-kotlin-plugin/src/test/java/org/sonarsource/kotlin/plugin/KotlinSensorTest.kt
@@ -220,11 +220,29 @@ internal class KotlinSensorTest : AbstractSensorTest() {
assertThat(issues).hasSize(2)
}
+ /**
+ * ```
+ * java.lang.IllegalStateException: Resolution is not performed
+ * at org.jetbrains.kotlin.analysis.api.descriptors.CliFe10AnalysisFacade.orThrowResolutionNotPerformedError(CliFe10AnalysisFacade.kt:78)
+ * at org.jetbrains.kotlin.analysis.api.descriptors.CliFe10AnalysisFacade.getAnalysisContext(CliFe10AnalysisFacade.kt:52)
+ * at org.jetbrains.kotlin.analysis.api.descriptors.CliFe10AnalysisFacade.getAnalysisContext(CliFe10AnalysisFacade.kt:41)
+ * at org.jetbrains.kotlin.analysis.api.descriptors.KaFe10SessionProvider.getAnalysisSession(KaFe10SessionProvider.kt:24)
+ * at org.sonarsource.kotlin.api.visiting.KotlinFileVisitor.scan(KotlinFileVisitor.kt:48)
+ * ```
+ * thrown by [org.jetbrains.kotlin.analysis.api.analyze]
+ */
@Test
fun `Ensure compiler crashes during BindingContext generation don't crash engine`() {
context.setCanSkipUnchangedFiles(false)
executeAnalysisWithInvalidBindingContext()
- assertThat(logTester.logs(Level.ERROR)).containsExactly("Could not generate binding context. Proceeding without semantics.")
+ assertThat(logTester.logs(Level.ERROR)).containsExactly(
+ "Could not generate binding context. Proceeding without semantics.",
+ "Cannot analyse 'file1.kt' with 'IssueSuppressionVisitor': Resolution is not performed",
+ "Cannot analyse 'file1.kt' with 'MetricVisitor': Resolution is not performed",
+ "Cannot analyse 'file1.kt' with 'KtChecksVisitor': Resolution is not performed",
+ "Cannot analyse 'file1.kt' with 'CopyPasteDetector': Resolution is not performed",
+ "Cannot analyse 'file1.kt' with 'SyntaxHighlighter': Resolution is not performed",
+ )
}
@Test
diff --git a/sonar-kotlin-plugin/src/test/java/org/sonarsource/kotlin/plugin/linking/WorkaroundForJarMinimizationTest.kt b/sonar-kotlin-plugin/src/test/java/org/sonarsource/kotlin/plugin/linking/WorkaroundForJarMinimizationTest.kt
index 9449595c9..95b77e262 100644
--- a/sonar-kotlin-plugin/src/test/java/org/sonarsource/kotlin/plugin/linking/WorkaroundForJarMinimizationTest.kt
+++ b/sonar-kotlin-plugin/src/test/java/org/sonarsource/kotlin/plugin/linking/WorkaroundForJarMinimizationTest.kt
@@ -22,6 +22,6 @@ import org.junit.jupiter.api.Test
internal class WorkaroundForJarMinimizationTest {
@Test
fun minimizing_class_count() {
- assertThat(WorkaroundForJarMinimization.CLASSES_TO_KEEP_WHEN_MINIMIZING_JAR).hasSize(7)
+ assertThat(WorkaroundForJarMinimization.CLASSES_TO_KEEP_WHEN_MINIMIZING_JAR).hasSize(16)
}
}
diff --git a/sonar-kotlin-test-api/src/main/java/org/sonarsource/kotlin/testapi/KotlinVerifier.kt b/sonar-kotlin-test-api/src/main/java/org/sonarsource/kotlin/testapi/KotlinVerifier.kt
index a9e569289..159ebfd9b 100644
--- a/sonar-kotlin-test-api/src/main/java/org/sonarsource/kotlin/testapi/KotlinVerifier.kt
+++ b/sonar-kotlin-test-api/src/main/java/org/sonarsource/kotlin/testapi/KotlinVerifier.kt
@@ -53,6 +53,7 @@ class KotlinVerifier(private val check: AbstractCheck) {
var deps: List = getClassPath(DEFAULT_TEST_JARS_DIRECTORY)
var isAndroid = false
var customDiagnostics: List? = null
+ var useK2 = false
fun verify() {
verifyFile {
@@ -70,10 +71,11 @@ class KotlinVerifier(private val check: AbstractCheck) {
val isScriptFile = filePath.extension == "kts"
val disposable = Disposer.newDisposable()
- val environment = Environment(disposable, classpath + deps, LanguageVersion.LATEST_STABLE)
+ val environment = Environment(disposable, classpath + deps, LanguageVersion.LATEST_STABLE, useK2 = useK2)
val converter = { content: String ->
val inputFile = TestInputFileBuilder("moduleKey", filePath.fileName.pathString)
.setCharset(StandardCharsets.UTF_8)
+ .setModuleBaseDir(baseDir)
.initMetadata(content).build()
if (isScriptFile) {
diff --git a/sonar-kotlin-test-api/src/main/java/org/sonarsource/kotlin/testapi/TestUtils.kt b/sonar-kotlin-test-api/src/main/java/org/sonarsource/kotlin/testapi/TestUtils.kt
index cbd6b693a..e1d430481 100644
--- a/sonar-kotlin-test-api/src/main/java/org/sonarsource/kotlin/testapi/TestUtils.kt
+++ b/sonar-kotlin-test-api/src/main/java/org/sonarsource/kotlin/testapi/TestUtils.kt
@@ -21,17 +21,34 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.sonar.api.batch.fs.InputFile
// TODO: testapi should not depend on frontend module.
import org.sonarsource.kotlin.api.frontend.Environment
+import org.sonarsource.kotlin.api.frontend.KotlinFileSystem
import org.sonarsource.kotlin.api.frontend.KotlinSyntaxStructure
import org.sonarsource.kotlin.api.frontend.KotlinTree
+import org.sonarsource.kotlin.api.frontend.KotlinVirtualFile
import org.sonarsource.kotlin.api.frontend.RegexCache
import org.sonarsource.kotlin.api.frontend.analyzeAndGetBindingContext
+import org.sonarsource.kotlin.api.frontend.createK2AnalysisSession
+import java.io.File
fun kotlinTreeOf(content: String, environment: Environment, inputFile: InputFile, doResolve: Boolean = true, providedDiagnostics: List? = null): KotlinTree {
+ if (environment.useK2) {
+ val virtualFile = KotlinVirtualFile(
+ KotlinFileSystem(),
+ File(inputFile.uri().path),
+ content,
+ )
+ environment.k2session = createK2AnalysisSession(
+ environment.disposable,
+ environment.configuration,
+ listOf(virtualFile),
+ )
+ }
+
val (ktFile, document) = KotlinSyntaxStructure.of(content, environment, inputFile)
- val bindingContext = if (doResolve) analyzeAndGetBindingContext(
+ val bindingContext = if (!environment.useK2 && doResolve) analyzeAndGetBindingContext(
environment.env,
listOf(ktFile),
) else BindingContext.EMPTY
- return KotlinTree(ktFile, document, bindingContext, providedDiagnostics ?: bindingContext.diagnostics.noSuppression().toList(), RegexCache())
+ return KotlinTree(ktFile, document, bindingContext, providedDiagnostics ?: bindingContext.diagnostics.noSuppression().toList(), RegexCache(), doResolve)
}