JS: allow to omit delegated constructor call for external classes in common FE. Prohibit delegated constructor call for external classes in JS FE.

This commit is contained in:
Alexey Andreev
2016-12-20 15:01:33 +03:00
parent 02ea1a4d64
commit 1a7e8b0690
18 changed files with 160 additions and 29 deletions
@@ -75,10 +75,13 @@ 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 }")
put(ErrorsJs.WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION, "Wrong initializer of external declaration. Must be ' = noImpl'")
put(ErrorsJs.WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER,
"Wrong default value for parameter of external function. Must be ' = noImpl'")
put(ErrorsJs.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL, "Delegated constructor call in external class")
put(ErrorsJs.EXTERNAL_DELEGATION, "Using delegate on external declaration")
this
}
@@ -80,9 +80,13 @@ public interface ErrorsJs {
ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
DiagnosticFactory0<KtExpression> NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE = DiagnosticFactory0.create(
ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT);
// Diagnostics about exposing implementation detail in external declarations
DiagnosticFactory0<KtExpression> WRONG_BODY_OF_EXTERNAL_DECLARATION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtElement> EXTERNAL_DELEGATED_CONSTRUCTOR_CALL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtElement> EXTERNAL_DELEGATION = DiagnosticFactory0.create(ERROR);
@SuppressWarnings("UnusedDeclaration")
Object _initializer = new Object() {
@@ -91,6 +91,7 @@ object JsExternalChecker : SimpleDeclarationChecker {
}
checkBody(declaration, descriptor, diagnosticHolder, bindingContext)
checkDelegation(declaration, descriptor, diagnosticHolder)
}
private fun checkBody(
@@ -114,6 +115,34 @@ object JsExternalChecker : SimpleDeclarationChecker {
}
}
private fun checkDelegation(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) {
if (descriptor !is MemberDescriptor || !DescriptorUtils.isEffectivelyExternal(descriptor)) return
if (declaration is KtClassOrObject) {
for (superTypeEntry in declaration.superTypeListEntries) {
when (superTypeEntry) {
is KtSuperTypeCallEntry -> {
diagnosticHolder.report(ErrorsJs.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL.on(superTypeEntry.valueArgumentList!!))
}
is KtDelegatedSuperTypeEntry -> {
diagnosticHolder.report(ErrorsJs.EXTERNAL_DELEGATION.on(superTypeEntry))
}
}
}
}
else if (declaration is KtSecondaryConstructor) {
val delegationCall = declaration.getDelegationCall()
if (!delegationCall.isImplicit) {
diagnosticHolder.report(ErrorsJs.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL.on(delegationCall))
}
}
else if (declaration is KtProperty && descriptor !is PropertyAccessorDescriptor) {
declaration.delegate?.let { delegate ->
diagnosticHolder.report(ErrorsJs.EXTERNAL_DELEGATION.on(delegate))
}
}
}
private fun isDirectlyExternal(declaration: KtDeclaration, descriptor: DeclarationDescriptor): Boolean {
if (declaration is KtProperty && descriptor is PropertyAccessorDescriptor) return false