[NoArg] Add implementation of plugin for FIR
This commit is contained in:
committed by
teamcity
parent
8acb8aa043
commit
5d0655247f
@@ -0,0 +1,27 @@
|
||||
description = "Kotlin NoArg Compiler Plugin (K2)"
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("jps-compatible")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":compiler:fir:cones"))
|
||||
compileOnly(project(":compiler:fir:tree"))
|
||||
compileOnly(project(":compiler:fir:resolve"))
|
||||
compileOnly(project(":compiler:fir:checkers"))
|
||||
compileOnly(project(":compiler:ir.backend.common"))
|
||||
compileOnly(project(":compiler:fir:entrypoint"))
|
||||
|
||||
compileOnly(intellijCore())
|
||||
runtimeOnly(kotlinStdlib())
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
"main" { projectDefault() }
|
||||
"test" { none() }
|
||||
}
|
||||
|
||||
runtimeJar()
|
||||
sourcesJar()
|
||||
javadocJar()
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.noarg.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirRegularClassChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
|
||||
|
||||
class FirNoArgCheckers(session: FirSession) : FirAdditionalCheckersExtension(session) {
|
||||
override val declarationCheckers: DeclarationCheckers = object : DeclarationCheckers() {
|
||||
override val regularClassCheckers: Set<FirRegularClassChecker> = setOf(FirNoArgDeclarationChecker)
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.noarg.fir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirRegularClassChecker
|
||||
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.caches.getValue
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInner
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
|
||||
object FirNoArgDeclarationChecker : FirRegularClassChecker() {
|
||||
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val source = declaration.source ?: return
|
||||
if (declaration.classKind != ClassKind.CLASS) return
|
||||
val matcher = context.session.noArgPredicateMatcher
|
||||
if (!matcher.isAnnotated(declaration.symbol)) return
|
||||
|
||||
when {
|
||||
declaration.isInner -> reporter.reportOn(source, KtErrorsNoArg.NOARG_ON_INNER_CLASS_ERROR, context)
|
||||
declaration.isLocal -> reporter.reportOn(source, KtErrorsNoArg.NOARG_ON_LOCAL_CLASS_ERROR, context)
|
||||
}
|
||||
|
||||
val superClassSymbol = declaration.symbol.getSuperClassSymbolOrAny(context.session)
|
||||
if (superClassSymbol.declarationSymbols.filterIsInstance<FirConstructorSymbol>().none { it.isNoArgConstructor() } && !matcher.isAnnotated(superClassSymbol)) {
|
||||
reporter.reportOn(source, KtErrorsNoArg.NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS, context)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun FirRegularClassSymbol.getSuperClassSymbolOrAny(session: FirSession): FirRegularClassSymbol {
|
||||
for (superType in resolvedSuperTypes) {
|
||||
val symbol = superType.fullyExpandedType(session).toRegularClassSymbol(session) ?: continue
|
||||
if (symbol.classKind == ClassKind.CLASS) return symbol
|
||||
}
|
||||
return session.builtinTypes.anyType.type.toRegularClassSymbol(session) ?: error("Symbol for Any not found")
|
||||
}
|
||||
|
||||
private fun FirConstructorSymbol.isNoArgConstructor(): Boolean {
|
||||
return valueParameterSymbols.all { it.hasDefaultValue }
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.noarg.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
|
||||
|
||||
class FirNoArgExtensionRegistrar(val noArgAnnotationFqNames: List<String>) : FirExtensionRegistrar() {
|
||||
override fun ExtensionRegistrarContext.configurePlugin() {
|
||||
+FirNoArgPredicateMatcher.getFactory(noArgAnnotationFqNames)
|
||||
+::FirNoArgCheckers
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.noarg.fir
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
|
||||
import org.jetbrains.kotlin.diagnostics.error0
|
||||
import org.jetbrains.kotlin.diagnostics.warning0
|
||||
|
||||
object KtErrorsNoArg {
|
||||
val NO_NOARG_CONSTRUCTOR_IN_SUPERCLASS by warning0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val NOARG_ON_INNER_CLASS_ERROR by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
val NOARG_ON_LOCAL_CLASS_ERROR by error0<PsiElement>(SourceElementPositioningStrategies.NAME_IDENTIFIER)
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.noarg.fir
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.caches.FirCache
|
||||
import org.jetbrains.kotlin.fir.caches.firCachesFactory
|
||||
import org.jetbrains.kotlin.fir.caches.getValue
|
||||
import org.jetbrains.kotlin.fir.extensions.predicate.has
|
||||
import org.jetbrains.kotlin.fir.extensions.predicate.metaHas
|
||||
import org.jetbrains.kotlin.fir.extensions.predicate.or
|
||||
import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider
|
||||
import org.jetbrains.kotlin.fir.extensions.utils.AbstractSimpleClassPredicateMatchingService
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
class FirNoArgPredicateMatcher(
|
||||
session: FirSession,
|
||||
noArgAnnotationFqNames: List<String>
|
||||
) : AbstractSimpleClassPredicateMatchingService(session) {
|
||||
companion object {
|
||||
fun getFactory(noArgAnnotationFqNames: List<String>): Factory {
|
||||
return Factory { session -> FirNoArgPredicateMatcher(session, noArgAnnotationFqNames) }
|
||||
}
|
||||
}
|
||||
|
||||
override val predicate = run {
|
||||
val annotationFqNames = noArgAnnotationFqNames.map { FqName(it) }
|
||||
has(annotationFqNames) or metaHas(annotationFqNames)
|
||||
}
|
||||
}
|
||||
|
||||
val FirSession.noArgPredicateMatcher: FirNoArgPredicateMatcher by FirSession.sessionComponentAccessor()
|
||||
Reference in New Issue
Block a user