Add FIR version of JspecifyDiagnosticComplianceHandler
This commit is contained in:
+67
-42
@@ -5,64 +5,89 @@
|
||||
|
||||
package org.jetbrains.kotlin.test.frontend.classic.handlers
|
||||
|
||||
import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo
|
||||
import org.jetbrains.kotlin.codeMetaInfo.model.DiagnosticCodeMetaInfo
|
||||
import org.jetbrains.kotlin.codeMetaInfo.model.JspecifyMarkerCodeMetaInfo
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.load.java.JSPECIFY_ANNOTATIONS_PACKAGE
|
||||
import org.jetbrains.kotlin.load.java.ReportLevel
|
||||
import org.jetbrains.kotlin.load.java.getDefaultReportLevelForAnnotation
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
|
||||
import org.jetbrains.kotlin.test.directives.ForeignAnnotationsDirectives
|
||||
import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
|
||||
import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
|
||||
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirAnalysisHandler
|
||||
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticCodeMetaInfo
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.model.TestModule
|
||||
import org.jetbrains.kotlin.test.services.TestServices
|
||||
import org.jetbrains.kotlin.test.services.globalMetadataInfoHandler
|
||||
import org.jetbrains.kotlin.test.services.sourceFileProvider
|
||||
|
||||
// Not that this diagnostic handler should be included only with `ClassicDiagnosticsHandler` and go after it
|
||||
class JspecifyDiagnosticComplianceHandler(testServices: TestServices) : ClassicFrontendAnalysisHandler(testServices) {
|
||||
override fun processModule(module: TestModule, info: ClassicFrontendOutputArtifact) {
|
||||
val jspecifyMode = module.directives[ForeignAnnotationsDirectives.JSPECIFY_STATE].singleOrNull()
|
||||
?: getDefaultReportLevelForAnnotation(JSPECIFY_ANNOTATIONS_PACKAGE)
|
||||
private fun TestServices.generateJspecifyMetadataInfos(
|
||||
module: TestModule, files: Iterable<TestFile>, diagnosticKind: (CodeMetaInfo) -> Any?
|
||||
) {
|
||||
val jspecifyMode = module.directives[ForeignAnnotationsDirectives.JSPECIFY_STATE].singleOrNull()
|
||||
?: getDefaultReportLevelForAnnotation(JSPECIFY_ANNOTATIONS_PACKAGE)
|
||||
val diagnosticsToJspecifyMarksForMode = diagnosticsToJspecifyMarks[jspecifyMode] ?: return
|
||||
|
||||
for ((testFile, ktFile) in info.allKtFiles) {
|
||||
val reportedDiagnostics =
|
||||
testServices.globalMetadataInfoHandler.getReportedMetaInfosForFile(testFile).filterIsInstance<DiagnosticCodeMetaInfo>()
|
||||
for (metaInfo in reportedDiagnostics) {
|
||||
val jspecifyMark = diagnosticsToJspecifyMarks.getValue(jspecifyMode)[metaInfo.diagnostic.factory] ?: continue
|
||||
val fileLines = ktFile.text.lines()
|
||||
val fileLinePositions =
|
||||
fileLines.map { it.length }.runningReduce { sumLength, length -> sumLength + length + 1 }
|
||||
val lineIndexToPasteJspecifyMark = fileLinePositions.indexOfLast { it < metaInfo.start }
|
||||
val positionToPasteJspecifyMark = fileLinePositions[lineIndexToPasteJspecifyMark]
|
||||
val offset = fileLines[lineIndexToPasteJspecifyMark + 1].takeWhile { it == ' ' }.length
|
||||
|
||||
testServices.globalMetadataInfoHandler.addMetadataInfosForFile(
|
||||
testFile,
|
||||
listOf(JspecifyMarkerCodeMetaInfo(positionToPasteJspecifyMark, positionToPasteJspecifyMark, offset, jspecifyMark))
|
||||
)
|
||||
}
|
||||
for (testFile in files) {
|
||||
val fileLines = sourceFileProvider.getContentOfSourceFile(testFile).lines()
|
||||
val fileLinePositions =
|
||||
fileLines.map { it.length }.runningReduce { sumLength, length -> sumLength + length + 1 }
|
||||
val newMetaInfos = globalMetadataInfoHandler.getReportedMetaInfosForFile(testFile).mapNotNull { metaInfo ->
|
||||
val diagnostic = diagnosticKind(metaInfo) ?: return@mapNotNull null
|
||||
val jspecifyMark = diagnosticsToJspecifyMarksForMode[diagnostic] ?: return@mapNotNull null
|
||||
val lineIndexToPasteJspecifyMark = fileLinePositions.indexOfLast { it < metaInfo.start }
|
||||
val positionToPasteJspecifyMark = fileLinePositions[lineIndexToPasteJspecifyMark]
|
||||
val offset = fileLines[lineIndexToPasteJspecifyMark + 1].takeWhile { it == ' ' }.length
|
||||
JspecifyMarkerCodeMetaInfo(positionToPasteJspecifyMark, positionToPasteJspecifyMark, offset, jspecifyMark)
|
||||
}
|
||||
globalMetadataInfoHandler.addMetadataInfosForFile(testFile, newMetaInfos)
|
||||
}
|
||||
}
|
||||
|
||||
internal val diagnosticsToJspecifyMarks = mapOf(
|
||||
ReportLevel.WARN to mapOf(
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
// TODO: list FIR warnings (they don't exist yet)
|
||||
),
|
||||
ReportLevel.STRICT to mapOf(
|
||||
Errors.TYPE_MISMATCH to "jspecify_nullness_mismatch",
|
||||
Errors.NULL_FOR_NONNULL_TYPE to "jspecify_nullness_mismatch",
|
||||
Errors.NOTHING_TO_OVERRIDE to "jspecify_nullness_mismatch",
|
||||
Errors.RETURN_TYPE_MISMATCH_ON_OVERRIDE to "jspecify_nullness_mismatch",
|
||||
Errors.UPPER_BOUND_VIOLATED to "jspecify_nullness_mismatch",
|
||||
Errors.UNSAFE_CALL to "jspecify_nullness_mismatch",
|
||||
|
||||
FirErrors.ARGUMENT_TYPE_MISMATCH to "jspecify_nullness_mismatch",
|
||||
FirErrors.NULL_FOR_NONNULL_TYPE to "jspecify_nullness_mismatch",
|
||||
FirErrors.NOTHING_TO_OVERRIDE to "jspecify_nullness_mismatch",
|
||||
FirErrors.RETURN_TYPE_MISMATCH_ON_OVERRIDE to "jspecify_nullness_mismatch",
|
||||
FirErrors.UPPER_BOUND_VIOLATED to "jspecify_nullness_mismatch",
|
||||
FirErrors.UNSAFE_CALL to "jspecify_nullness_mismatch",
|
||||
),
|
||||
ReportLevel.IGNORE to emptyMap()
|
||||
)
|
||||
|
||||
class JspecifyDiagnosticComplianceHandler(testServices: TestServices) : ClassicFrontendAnalysisHandler(testServices) {
|
||||
override fun processModule(module: TestModule, info: ClassicFrontendOutputArtifact) =
|
||||
testServices.generateJspecifyMetadataInfos(module, info.allKtFiles.keys) {
|
||||
(it as? DiagnosticCodeMetaInfo)?.diagnostic?.factory
|
||||
}
|
||||
|
||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val diagnosticsToJspecifyMarks = mapOf(
|
||||
ReportLevel.WARN to mapOf(
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
ErrorsJvm.RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS to "jspecify_nullness_mismatch",
|
||||
),
|
||||
ReportLevel.STRICT to mapOf(
|
||||
Errors.TYPE_MISMATCH to "jspecify_nullness_mismatch",
|
||||
Errors.NULL_FOR_NONNULL_TYPE to "jspecify_nullness_mismatch",
|
||||
Errors.NOTHING_TO_OVERRIDE to "jspecify_nullness_mismatch",
|
||||
Errors.RETURN_TYPE_MISMATCH_ON_OVERRIDE to "jspecify_nullness_mismatch",
|
||||
Errors.UPPER_BOUND_VIOLATED to "jspecify_nullness_mismatch",
|
||||
Errors.UNSAFE_CALL to "jspecify_nullness_mismatch",
|
||||
),
|
||||
ReportLevel.IGNORE to emptyMap()
|
||||
)
|
||||
}
|
||||
}
|
||||
class FirJspecifyDiagnosticComplianceHandler(testServices: TestServices) : FirAnalysisHandler(testServices) {
|
||||
override fun processModule(module: TestModule, info: FirOutputArtifact) =
|
||||
testServices.generateJspecifyMetadataInfos(module, info.allFirFiles.keys) {
|
||||
(it as? FirDiagnosticCodeMetaInfo)?.diagnostic?.factory
|
||||
}
|
||||
|
||||
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.test.preprocessors
|
||||
|
||||
import org.jetbrains.kotlin.test.frontend.classic.handlers.JspecifyDiagnosticComplianceHandler.Companion.diagnosticsToJspecifyMarks
|
||||
import org.jetbrains.kotlin.test.frontend.classic.handlers.diagnosticsToJspecifyMarks
|
||||
import org.jetbrains.kotlin.test.model.TestFile
|
||||
import org.jetbrains.kotlin.test.services.*
|
||||
|
||||
|
||||
Reference in New Issue
Block a user