[FIR] Move all checkers and theirs infrastructure to separate module
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile(project(":compiler:fir:resolve"))
|
||||
|
||||
compileOnly(project(":kotlin-reflect-api"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { none() }
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.call
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
|
||||
object CallCheckers {
|
||||
val EXPRESSIONS: List<FirExpressionChecker<FirExpression>> = listOf()
|
||||
val QUALIFIED_ACCESS: List<FirQualifiedAccessChecker> = listOf<FirQualifiedAccessChecker>() + EXPRESSIONS
|
||||
val FUNCTION_CALLS: List<FirFunctionCallChecker> = listOf<FirFunctionCallChecker>() + QUALIFIED_ACCESS
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.call
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
|
||||
abstract class FirExpressionChecker<in E : FirExpression> {
|
||||
abstract fun check(functionCall: E, reporter: DiagnosticReporter)
|
||||
}
|
||||
|
||||
typealias FirFunctionCallChecker = FirExpressionChecker<FirFunctionCall>
|
||||
typealias FirQualifiedAccessChecker = FirExpressionChecker<FirQualifiedAccessExpression>
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
|
||||
object DeclarationCheckers {
|
||||
val DECLARATIONS: List<FirDeclarationChecker<FirDeclaration>> = listOf()
|
||||
val MEMBER_DECLARATIONS: List<FirDeclarationChecker<FirMemberDeclaration>> = DECLARATIONS + listOf(
|
||||
FirInfixFunctionDeclarationChecker
|
||||
)
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
|
||||
|
||||
abstract class FirDeclarationChecker<in D : FirDeclaration> {
|
||||
abstract fun check(declaration: D, reporter: DiagnosticReporter)
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.onSource
|
||||
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.isInfix
|
||||
|
||||
object FirInfixFunctionDeclarationChecker : FirDeclarationChecker<FirMemberDeclaration>() {
|
||||
override fun check(declaration: FirMemberDeclaration, reporter: DiagnosticReporter) {
|
||||
if (declaration is FirSimpleFunction && declaration.isInfix) {
|
||||
if (declaration.valueParameters.size != 1 || declaration.receiverTypeRef == null) {
|
||||
reporter.report(declaration.source)
|
||||
}
|
||||
return
|
||||
}
|
||||
if (declaration.isInfix) {
|
||||
reporter.report(declaration.source)
|
||||
}
|
||||
}
|
||||
|
||||
private fun DiagnosticReporter.report(source: FirSourceElement?) {
|
||||
source?.let { report(Errors.INAPPLICABLE_INFIX_MODIFIER.onSource(it, "Inapplicable infix modifier")) }
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.DeclarationCheckersDiagnosticComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.ErrorNodeDiagnosticCollectorComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.components.ExpressionCheckersDiagnosticComponent
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
|
||||
abstract class AbstractDiagnosticCollector {
|
||||
fun collectDiagnostics(firFile: FirFile): Iterable<ConeDiagnostic> {
|
||||
if (!componentsInitialized) {
|
||||
throw IllegalStateException("Components are not initialized")
|
||||
}
|
||||
initializeCollector()
|
||||
firFile.accept(visitor)
|
||||
return getCollectedDiagnostics()
|
||||
}
|
||||
|
||||
protected abstract fun initializeCollector()
|
||||
protected abstract fun getCollectedDiagnostics(): Iterable<ConeDiagnostic>
|
||||
abstract fun runCheck(block: (DiagnosticReporter) -> Unit)
|
||||
|
||||
private val components: MutableList<AbstractDiagnosticCollectorComponent> = mutableListOf()
|
||||
private var componentsInitialized = false
|
||||
private val visitor = Visitor()
|
||||
|
||||
fun initializeComponents(vararg components: AbstractDiagnosticCollectorComponent) {
|
||||
if (componentsInitialized) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
this.components += components
|
||||
componentsInitialized = true
|
||||
}
|
||||
|
||||
private inner class Visitor : FirVisitorVoid() {
|
||||
private fun <T : FirElement> T.runComponents() {
|
||||
components.forEach {
|
||||
this.accept(it)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitElement(element: FirElement) {
|
||||
element.runComponents()
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun AbstractDiagnosticCollector.registerAllComponents() {
|
||||
initializeComponents(
|
||||
DeclarationCheckersDiagnosticComponent(this),
|
||||
ExpressionCheckersDiagnosticComponent(this),
|
||||
ErrorNodeDiagnosticCollectorComponent(this),
|
||||
)
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors
|
||||
|
||||
object FirDiagnosticsCollector {
|
||||
fun create(): AbstractDiagnosticCollector {
|
||||
val collector = SimpleDiagnosticsCollector()
|
||||
collector.registerAllComponents()
|
||||
return collector
|
||||
}
|
||||
|
||||
// Use in CLI compiler
|
||||
@Suppress("unused")
|
||||
fun createParallel(): AbstractDiagnosticCollector {
|
||||
val collector = ParallelDiagnosticsCollector(4)
|
||||
collector.registerAllComponents()
|
||||
return collector
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.SimpleDiagnosticReporter
|
||||
import java.util.*
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.Future
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
class ParallelDiagnosticsCollector(private val numberOfThreads: Int) : AbstractDiagnosticCollector() {
|
||||
init {
|
||||
require(numberOfThreads >= 1) {
|
||||
"Number of threads should be at least 1"
|
||||
}
|
||||
}
|
||||
|
||||
private var reporters = initializeReporters()
|
||||
private val collectorLocalIndex = ThreadLocal<Int>()
|
||||
private val collectorIndexCounter = AtomicInteger()
|
||||
private val futures = LinkedList<Future<*>>()
|
||||
|
||||
private val pool = Executors.newFixedThreadPool(numberOfThreads) { runnable ->
|
||||
Thread {
|
||||
collectorLocalIndex.set(collectorIndexCounter.getAndIncrement())
|
||||
runnable.run()
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeReporters(): List<SimpleDiagnosticReporter> {
|
||||
return (1..numberOfThreads).map { SimpleDiagnosticReporter() }
|
||||
}
|
||||
|
||||
override fun initializeCollector() {
|
||||
reporters = initializeReporters()
|
||||
futures.clear()
|
||||
}
|
||||
|
||||
override fun getCollectedDiagnostics(): Iterable<ConeDiagnostic> {
|
||||
futures.forEach { it.get() }
|
||||
return Iterable {
|
||||
object : Iterator<ConeDiagnostic> {
|
||||
private val globalIterator = reporters.iterator()
|
||||
private var localIterator = globalIterator.next().diagnostics.iterator()
|
||||
|
||||
private fun update() {
|
||||
while (!localIterator.hasNext() && globalIterator.hasNext()) {
|
||||
localIterator = globalIterator.next().diagnostics.iterator()
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
update()
|
||||
return localIterator.hasNext()
|
||||
}
|
||||
|
||||
override fun next(): ConeDiagnostic {
|
||||
update()
|
||||
return localIterator.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun runCheck(block: (DiagnosticReporter) -> Unit) {
|
||||
futures += pool.submit {
|
||||
val reporter = reporters[collectorLocalIndex.get()]
|
||||
block(reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.SimpleDiagnosticReporter
|
||||
|
||||
class SimpleDiagnosticsCollector : AbstractDiagnosticCollector() {
|
||||
private var reporter = SimpleDiagnosticReporter()
|
||||
|
||||
override fun initializeCollector() {
|
||||
reporter = SimpleDiagnosticReporter()
|
||||
}
|
||||
|
||||
override fun getCollectedDiagnostics(): Iterable<ConeDiagnostic> {
|
||||
return reporter.diagnostics
|
||||
}
|
||||
|
||||
override fun runCheck(block: (DiagnosticReporter) -> Unit) {
|
||||
block(reporter)
|
||||
}
|
||||
}
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors.components
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
|
||||
abstract class AbstractDiagnosticCollectorComponent(private val collector: AbstractDiagnosticCollector) : FirVisitorVoid() {
|
||||
override fun visitElement(element: FirElement) {}
|
||||
|
||||
protected fun runCheck(block: (DiagnosticReporter) -> Unit) {
|
||||
collector.runCheck(block)
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors.components
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirDeclarationChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
|
||||
class DeclarationCheckersDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
override fun visitProperty(property: FirProperty) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(property, it) }
|
||||
}
|
||||
|
||||
override fun visitRegularClass(regularClass: FirRegularClass) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(regularClass, it) }
|
||||
}
|
||||
|
||||
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(simpleFunction, it) }
|
||||
}
|
||||
|
||||
override fun visitTypeAlias(typeAlias: FirTypeAlias) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(typeAlias, it) }
|
||||
}
|
||||
|
||||
override fun visitConstructor(constructor: FirConstructor) {
|
||||
runCheck { DeclarationCheckers.MEMBER_DECLARATIONS.check(constructor, it) }
|
||||
}
|
||||
|
||||
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(anonymousFunction, it) }
|
||||
}
|
||||
|
||||
override fun visitPropertyAccessor(propertyAccessor: FirPropertyAccessor) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(propertyAccessor, it) }
|
||||
}
|
||||
|
||||
override fun visitValueParameter(valueParameter: FirValueParameter) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(valueParameter, it) }
|
||||
}
|
||||
|
||||
override fun visitEnumEntry(enumEntry: FirEnumEntry) {
|
||||
runCheck { DeclarationCheckers.DECLARATIONS.check(enumEntry, it) }
|
||||
}
|
||||
|
||||
private fun <D : FirDeclaration> List<FirDeclarationChecker<D>>.check(declaration: D, reporter: DiagnosticReporter) {
|
||||
for (checker in this) {
|
||||
checker.check(declaration, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors.components
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.onSource
|
||||
import org.jetbrains.kotlin.fir.declarations.FirErrorFunction
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirStubDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirErrorLoop
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
|
||||
class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
override fun visitErrorLoop(errorLoop: FirErrorLoop) {
|
||||
val source = errorLoop.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorLoop.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef) {
|
||||
val source = errorTypeRef.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorTypeRef.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference) {
|
||||
val source = errorNamedReference.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorNamedReference.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorExpression(errorExpression: FirErrorExpression) {
|
||||
val source = errorExpression.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorExpression.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
override fun visitErrorFunction(errorFunction: FirErrorFunction) {
|
||||
val source = errorFunction.source ?: return
|
||||
runCheck { reportFirDiagnostic(errorFunction.diagnostic, source, it) }
|
||||
}
|
||||
|
||||
private fun reportFirDiagnostic(diagnostic: FirDiagnostic, source: FirSourceElement, reporter: DiagnosticReporter) {
|
||||
val coneDiagnostic = when (diagnostic) {
|
||||
is FirUnresolvedReferenceError -> FirErrors.UNRESOLVED_REFERENCE.onSource(source, diagnostic.name?.asString())
|
||||
is FirUnresolvedSymbolError -> FirErrors.UNRESOLVED_REFERENCE.onSource(source, diagnostic.classId.asString())
|
||||
is FirUnresolvedNameError -> FirErrors.UNRESOLVED_REFERENCE.onSource(source, diagnostic.name.asString())
|
||||
is FirInapplicableCandidateError -> FirErrors.INAPPLICABLE_CANDIDATE.onSource(source, diagnostic.candidates.map { it.symbol })
|
||||
is FirAmbiguityError -> FirErrors.AMBIGUITY.onSource(source, diagnostic.candidates)
|
||||
is FirOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.onSource(source, diagnostic.candidates)
|
||||
is FirVariableExpectedError -> Errors.VARIABLE_EXPECTED.onSource(source)
|
||||
is FirTypeMismatchError -> FirErrors.TYPE_MISMATCH.onSource(source, diagnostic.expectedType, diagnostic.actualType)
|
||||
is FirSimpleDiagnostic -> diagnostic.getFactory().onSource(source)
|
||||
is FirStubDiagnostic -> null
|
||||
else -> throw IllegalArgumentException("Unsupported diagnostic type: ${diagnostic.javaClass}")
|
||||
}
|
||||
reporter.report(coneDiagnostic)
|
||||
}
|
||||
|
||||
private fun FirSimpleDiagnostic.getFactory(): DiagnosticFactory0<PsiElement> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return when (kind) {
|
||||
DiagnosticKind.Syntax -> FirErrors.SYNTAX_ERROR
|
||||
DiagnosticKind.ReturnNotAllowed -> Errors.RETURN_NOT_ALLOWED
|
||||
DiagnosticKind.UnresolvedLabel -> FirErrors.UNRESOLVED_LABEL
|
||||
DiagnosticKind.IllegalConstExpression -> FirErrors.ILLEGAL_CONST_EXPRESSION
|
||||
DiagnosticKind.ConstructorInObject -> Errors.CONSTRUCTOR_IN_OBJECT
|
||||
DiagnosticKind.DeserializationError -> FirErrors.DESERIALIZATION_ERROR
|
||||
DiagnosticKind.InferenceError -> FirErrors.INFERENCE_ERROR
|
||||
DiagnosticKind.NoSupertype -> FirErrors.NO_SUPERTYPE
|
||||
DiagnosticKind.TypeParameterAsSupertype -> FirErrors.TYPE_PARAMETER_AS_SUPERTYPE
|
||||
DiagnosticKind.EnumAsSupertype -> FirErrors.ENUM_AS_SUPERTYPE
|
||||
DiagnosticKind.RecursionInSupertypes -> FirErrors.RECURSION_IN_SUPERTYPES
|
||||
DiagnosticKind.RecursionInImplicitTypes -> FirErrors.RECURSION_IN_IMPLICIT_TYPES
|
||||
DiagnosticKind.Java -> FirErrors.ERROR_FROM_JAVA_RESOLUTION
|
||||
DiagnosticKind.Other -> FirErrors.OTHER_ERROR
|
||||
} as DiagnosticFactory0<PsiElement>
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.collectors.components
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.call.CallCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.call.FirExpressionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
|
||||
class ExpressionCheckersDiagnosticComponent(collector: AbstractDiagnosticCollector) : AbstractDiagnosticCollectorComponent(collector) {
|
||||
override fun visitTypeOperatorCall(typeOperatorCall: FirTypeOperatorCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(typeOperatorCall, it) }
|
||||
}
|
||||
|
||||
override fun <T> visitConstExpression(constExpression: FirConstExpression<T>) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(constExpression, it) }
|
||||
}
|
||||
|
||||
override fun visitAnnotationCall(annotationCall: FirAnnotationCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(annotationCall, it) }
|
||||
}
|
||||
|
||||
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) {
|
||||
runCheck { CallCheckers.QUALIFIED_ACCESS.check(qualifiedAccessExpression, it) }
|
||||
}
|
||||
|
||||
override fun visitFunctionCall(functionCall: FirFunctionCall) {
|
||||
runCheck { CallCheckers.FUNCTION_CALLS.check(functionCall, it) }
|
||||
}
|
||||
|
||||
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess) {
|
||||
runCheck { CallCheckers.QUALIFIED_ACCESS.check(callableReferenceAccess, it) }
|
||||
}
|
||||
|
||||
override fun visitThisReceiverExpression(thisReceiverExpression: FirThisReceiverExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(thisReceiverExpression, it) }
|
||||
}
|
||||
|
||||
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(resolvedQualifier, it) }
|
||||
}
|
||||
|
||||
override fun visitWhenExpression(whenExpression: FirWhenExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(whenExpression, it) }
|
||||
}
|
||||
|
||||
override fun visitBinaryLogicExpression(binaryLogicExpression: FirBinaryLogicExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(binaryLogicExpression, it) }
|
||||
}
|
||||
|
||||
override fun visitArrayOfCall(arrayOfCall: FirArrayOfCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(arrayOfCall, it) }
|
||||
}
|
||||
|
||||
override fun visitStringConcatenationCall(stringConcatenationCall: FirStringConcatenationCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(stringConcatenationCall, it) }
|
||||
}
|
||||
|
||||
override fun visitCheckNotNullCall(checkNotNullCall: FirCheckNotNullCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(checkNotNullCall, it) }
|
||||
}
|
||||
|
||||
override fun visitTryExpression(tryExpression: FirTryExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(tryExpression, it) }
|
||||
}
|
||||
|
||||
override fun visitClassReferenceExpression(classReferenceExpression: FirClassReferenceExpression) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(classReferenceExpression, it) }
|
||||
}
|
||||
|
||||
override fun visitGetClassCall(getClassCall: FirGetClassCall) {
|
||||
runCheck { CallCheckers.EXPRESSIONS.check(getClassCall, it) }
|
||||
}
|
||||
|
||||
private fun <E : FirExpression> List<FirExpressionChecker<E>>.check(expression: E, reporter: DiagnosticReporter) {
|
||||
for (checker in this) {
|
||||
checker.check(expression, reporter)
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.psi
|
||||
|
||||
class ConeDiagnostic(
|
||||
val diagnostic: Diagnostic,
|
||||
val source: FirSourceElement
|
||||
)
|
||||
|
||||
inline fun <reified E : PsiElement> DiagnosticFactory0<E>.onSource(source: FirSourceElement): ConeDiagnostic? {
|
||||
val psi = source.psi as? E ?: return null
|
||||
return ConeDiagnostic(this.on(psi), source)
|
||||
}
|
||||
|
||||
inline fun <reified E : PsiElement, A> DiagnosticFactory1<E, A>.onSource(source: FirSourceElement, a: A): ConeDiagnostic? {
|
||||
val psi = source.psi as? E ?: return null
|
||||
return ConeDiagnostic(this.on(psi, a), source)
|
||||
}
|
||||
|
||||
inline fun <reified E : PsiElement, A, B> DiagnosticFactory2<E, A, B>.onSource(source: FirSourceElement, a: A, b: B): ConeDiagnostic? {
|
||||
val psi = source.psi as? E ?: return null
|
||||
return ConeDiagnostic(this.on(psi, a, b), source)
|
||||
}
|
||||
|
||||
inline fun <reified E : PsiElement, A, B, C> DiagnosticFactory3<E, A, B, C>.onSource(source: FirSourceElement, a: A, b: B, c: C): ConeDiagnostic? {
|
||||
val psi = source.psi as? E ?: return null
|
||||
return ConeDiagnostic(this.on(psi, a, b, c), source)
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.AMBIGUITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ASSIGN_OPERATOR_AMBIGUITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ENUM_AS_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ERROR_FROM_JAVA_RESOLUTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ILLEGAL_CONST_EXPRESSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INAPPLICABLE_CANDIDATE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INFERENCE_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NO_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OTHER_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_IMPLICIT_TYPES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RECURSION_IN_SUPERTYPES
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SYNTAX_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_AS_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_LABEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNRESOLVED_REFERENCE
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderer
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
|
||||
@Suppress("unused")
|
||||
class DefaultErrorMessagesFir : DefaultErrorMessages.Extension {
|
||||
|
||||
override fun getMap(): DiagnosticFactoryToRendererMap {
|
||||
return MAP
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SYMBOL_COLLECTION_RENDERER = Renderer { symbols: Collection<AbstractFirBasedSymbol<*>> ->
|
||||
symbols.joinToString(prefix = "[", postfix = "]", separator = ",", limit = 3, truncated = "...") { symbol ->
|
||||
when (symbol) {
|
||||
is FirClassLikeSymbol<*> -> symbol.classId.asString()
|
||||
is FirCallableSymbol<*> -> symbol.callableId.toString()
|
||||
else -> "???"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val MAP = DiagnosticFactoryToRendererMap("FIR").also { map ->
|
||||
map.put(UNRESOLVED_REFERENCE, "Unresolved reference: {0}", Renderer { it })
|
||||
map.put(INAPPLICABLE_CANDIDATE, "Inapplicable candidate(s): {0}", SYMBOL_COLLECTION_RENDERER)
|
||||
map.put(AMBIGUITY, "Ambiguity between candidates: {0}", SYMBOL_COLLECTION_RENDERER)
|
||||
map.put(ASSIGN_OPERATOR_AMBIGUITY, "Ambiguity between assign operator candidates: {0}", SYMBOL_COLLECTION_RENDERER)
|
||||
map.put(SYNTAX_ERROR, "Syntax error")
|
||||
map.put(UNRESOLVED_LABEL, "Unresolved label")
|
||||
map.put(ILLEGAL_CONST_EXPRESSION, "Illegal const expression")
|
||||
map.put(DESERIALIZATION_ERROR, "Deserialization error")
|
||||
map.put(INFERENCE_ERROR, "Inference error")
|
||||
map.put(NO_SUPERTYPE, "No supertype")
|
||||
map.put(TYPE_PARAMETER_AS_SUPERTYPE, "Type parameter as supertype")
|
||||
map.put(ENUM_AS_SUPERTYPE, "Enum as supertype")
|
||||
map.put(RECURSION_IN_SUPERTYPES, "Recursion in supertypes")
|
||||
map.put(RECURSION_IN_IMPLICIT_TYPES, "Recursion in implicit types")
|
||||
map.put(ERROR_FROM_JAVA_RESOLUTION, "Java resolution error")
|
||||
map.put(OTHER_ERROR, "Unknown (other) error")
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
abstract class DiagnosticReporter {
|
||||
abstract fun report(diagnostic: ConeDiagnostic?)
|
||||
}
|
||||
|
||||
class SimpleDiagnosticReporter : DiagnosticReporter() {
|
||||
val diagnostics: MutableList<ConeDiagnostic> = mutableListOf()
|
||||
|
||||
override fun report(diagnostic: ConeDiagnostic?) {
|
||||
if (diagnostic == null) return
|
||||
diagnostics += diagnostic
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
|
||||
package org.jetbrains.kotlin.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import kotlin.reflect.full.memberProperties
|
||||
|
||||
fun FirErrors.registerExternalFactories() {
|
||||
val klass = FirErrors::class
|
||||
for (property in klass.memberProperties) {
|
||||
val factory = property.get(this) as? DiagnosticFactory<*> ?: continue
|
||||
factory.name = property.name
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.*
|
||||
import org.jetbrains.kotlin.diagnostics.Severity.ERROR
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
|
||||
object FirErrors {
|
||||
val UNRESOLVED_REFERENCE = DiagnosticFactory1.create<KtElement, String?>(ERROR)
|
||||
val INAPPLICABLE_CANDIDATE = DiagnosticFactory1.create<KtElement, Collection<AbstractFirBasedSymbol<*>>>(ERROR)
|
||||
val AMBIGUITY = DiagnosticFactory1.create<KtElement, Collection<AbstractFirBasedSymbol<*>>>(ERROR)
|
||||
val ASSIGN_OPERATOR_AMBIGUITY = DiagnosticFactory1.create<KtElement, Collection<AbstractFirBasedSymbol<*>>>(ERROR)
|
||||
val SYNTAX_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val UNRESOLVED_LABEL = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val ILLEGAL_CONST_EXPRESSION = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val DESERIALIZATION_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val INFERENCE_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val NO_SUPERTYPE = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val TYPE_PARAMETER_AS_SUPERTYPE = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val ENUM_AS_SUPERTYPE = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val RECURSION_IN_SUPERTYPES = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val RECURSION_IN_IMPLICIT_TYPES = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val ERROR_FROM_JAVA_RESOLUTION = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val OTHER_ERROR = DiagnosticFactory0.create<KtElement>(ERROR)
|
||||
val TYPE_MISMATCH = DiagnosticFactory2.create<KtElement, ConeKotlinType, ConeKotlinType>(ERROR)
|
||||
|
||||
init {
|
||||
registerExternalFactories()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user