JS: prohibit external functions and accessors with bodies other than noImpl. Prohibit to use anything except noImpl for default parameters initializers in external functions. See KT-13892
This commit is contained in:
+1
@@ -75,6 +75,7 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
put(ErrorsJs.INLINE_EXTERNAL_DECLARATION, "Inline external declaration")
|
||||
put(ErrorsJs.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE,
|
||||
"Only nullable properties of external interfaces are allowed to be non-abstract")
|
||||
put(ErrorsJs.WRONG_BODY_OF_EXTERNAL_DECLARATION, "Wrong body of external declaration. Must be either ' = noImpl' or { noImpl }")
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
@@ -78,8 +78,9 @@ public interface ErrorsJs {
|
||||
ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory0<KtDeclaration> INLINE_EXTERNAL_DECLARATION = DiagnosticFactory0.create(
|
||||
ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory0<KtDeclaration> NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE = DiagnosticFactory0.create(
|
||||
DiagnosticFactory0<KtExpression> NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE = DiagnosticFactory0.create(
|
||||
ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory0<KtExpression> WRONG_BODY_OF_EXTERNAL_DECLARATION = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
|
||||
+34
-2
@@ -22,18 +22,22 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.js.PredefinedAnnotation
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.utils.singletonOrEmptyList
|
||||
|
||||
object JsExternalChecker : SimpleDeclarationChecker {
|
||||
val NO_IMPL_PROPERTY_NAME = FqNameUnsafe("kotlin.js.noImpl")
|
||||
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink,
|
||||
bindingContext: BindingContext) {
|
||||
if (!AnnotationsUtils.isNativeObject(descriptor)) return
|
||||
@@ -85,6 +89,34 @@ object JsExternalChecker : SimpleDeclarationChecker {
|
||||
) {
|
||||
diagnosticHolder.report(ErrorsJs.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE.on(declaration))
|
||||
}
|
||||
|
||||
checkBody(declaration, diagnosticHolder, bindingContext)
|
||||
}
|
||||
|
||||
private fun checkBody(declaration: KtDeclaration, diagnosticHolder: DiagnosticSink, bindingContext: BindingContext) {
|
||||
if (declaration is KtDeclarationWithBody && !declaration.hasValidExternalBody(bindingContext)) {
|
||||
reportWrongBody(declaration.bodyExpression!!, diagnosticHolder, bindingContext)
|
||||
}
|
||||
else if (declaration is KtDeclarationWithInitializer && declaration.initializer?.isNoImplExpression(bindingContext) == false) {
|
||||
reportWrongBody(declaration.initializer!!, diagnosticHolder, bindingContext)
|
||||
}
|
||||
if (declaration is KtCallableDeclaration) {
|
||||
for (defaultValue in declaration.valueParameters.mapNotNull { it.defaultValue }) {
|
||||
checkExternalExpression(defaultValue, diagnosticHolder, bindingContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkExternalExpression(expression: KtExpression, diagnosticHolder: DiagnosticSink, bindingContext: BindingContext) {
|
||||
if (!expression.isNoImplExpression(bindingContext)) {
|
||||
reportWrongBody(expression, diagnosticHolder, bindingContext)
|
||||
}
|
||||
}
|
||||
|
||||
private fun reportWrongBody(expression: KtExpression, diagnosticHolder: DiagnosticSink, bindingContext: BindingContext) {
|
||||
if (bindingContext.diagnostics.forElement(expression).none { it.factory == ErrorsJs.WRONG_BODY_OF_EXTERNAL_DECLARATION }) {
|
||||
diagnosticHolder.report(ErrorsJs.WRONG_BODY_OF_EXTERNAL_DECLARATION.on(expression))
|
||||
}
|
||||
}
|
||||
|
||||
private fun isDirectlyExternal(declaration: KtDeclaration, descriptor: DeclarationDescriptor): Boolean {
|
||||
|
||||
Reference in New Issue
Block a user