Introduce DeclarationCheckerContext, remove SimpleDeclarationChecker

This commit is contained in:
Alexander Udalov
2018-01-03 12:55:59 +01:00
parent 4cb5483c13
commit 8cd7686535
33 changed files with 249 additions and 527 deletions
@@ -19,18 +19,14 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.naming.NameSuggestion
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
class JsBuiltinNameClashChecker(private val nameSuggestion: NameSuggestion) : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration, descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
) {
class JsBuiltinNameClashChecker(private val nameSuggestion: NameSuggestion) : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (AnnotationsUtils.isNativeObject(descriptor)) return
if (descriptor.containingDeclaration !is ClassDescriptor) return
@@ -40,12 +36,12 @@ class JsBuiltinNameClashChecker(private val nameSuggestion: NameSuggestion) : Si
if (descriptor is ClassDescriptor) {
if (simpleName in PROHIBITED_STATIC_NAMES) {
diagnosticHolder.report(ErrorsJs.JS_BUILTIN_NAME_CLASH.on(declaration, "Function.$simpleName"))
context.trace.report(ErrorsJs.JS_BUILTIN_NAME_CLASH.on(declaration, "Function.$simpleName"))
}
}
else if (descriptor is CallableMemberDescriptor) {
if (simpleName in PROHIBITED_MEMBER_NAMES) {
diagnosticHolder.report(ErrorsJs.JS_BUILTIN_NAME_CLASH.on(declaration, "Object.prototype.$simpleName"))
context.trace.report(ErrorsJs.JS_BUILTIN_NAME_CLASH.on(declaration, "Object.prototype.$simpleName"))
}
}
}
@@ -57,4 +53,4 @@ class JsBuiltinNameClashChecker(private val nameSuggestion: NameSuggestion) : Si
@JvmField
val PROHIBITED_MEMBER_NAMES = setOf("constructor")
}
}
}
@@ -18,37 +18,35 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.types.isDynamic
object JsDynamicDeclarationChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration, descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
) {
object JsDynamicDeclarationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val trace = context.trace
if (declaration is KtProperty && descriptor is VariableDescriptorWithAccessors) {
declaration.delegateExpression?.let { delegateExpression ->
val provideDelegateCall = bindingContext[BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor]
val provideDelegateCall = trace[BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, descriptor]
if (provideDelegateCall != null && provideDelegateCall.resultingDescriptor.returnType?.isDynamic() == true ||
bindingContext.getType(delegateExpression)?.isDynamic() == true
trace.getType(delegateExpression)?.isDynamic() == true
) {
diagnosticHolder.report(ErrorsJs.PROPERTY_DELEGATION_BY_DYNAMIC.on(delegateExpression))
trace.report(ErrorsJs.PROPERTY_DELEGATION_BY_DYNAMIC.on(delegateExpression))
}
}
}
else if (declaration is KtClassOrObject) {
for (delegateDecl in declaration.superTypeListEntries.filterIsInstance<KtDelegatedSuperTypeEntry>()) {
val delegateExpr = delegateDecl.delegateExpression ?: continue
if (bindingContext.getType(delegateExpr)?.isDynamic() == true) {
diagnosticHolder.report(ErrorsJs.DELEGATION_BY_DYNAMIC.on(delegateExpr))
if (trace.getType(delegateExpr)?.isDynamic() == true) {
trace.report(ErrorsJs.DELEGATION_BY_DYNAMIC.on(delegateExpr))
}
}
}
}
}
}
@@ -28,44 +28,45 @@ 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.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.TypeUtils
object JsExternalChecker : SimpleDeclarationChecker {
object JsExternalChecker : DeclarationChecker {
val DEFINED_EXTERNALLY_PROPERTY_NAMES = setOf(FqNameUnsafe("kotlin.js.noImpl"), FqNameUnsafe("kotlin.js.definedExternally"))
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext) {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (!AnnotationsUtils.isNativeObject(descriptor)) return
val trace = context.trace
if (!DescriptorUtils.isTopLevelDeclaration(descriptor)) {
if (isDirectlyExternal(declaration, descriptor) && descriptor !is PropertyAccessorDescriptor) {
diagnosticHolder.report(ErrorsJs.NESTED_EXTERNAL_DECLARATION.on(declaration))
trace.report(ErrorsJs.NESTED_EXTERNAL_DECLARATION.on(declaration))
}
}
if (DescriptorUtils.isAnnotationClass(descriptor)) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "annotation class"))
trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "annotation class"))
}
else if (descriptor is ClassDescriptor && descriptor.isData) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "data class"))
trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "data class"))
}
else if (descriptor is PropertyAccessorDescriptor && isDirectlyExternal(declaration, descriptor)) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "property accessor"))
trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "property accessor"))
}
else if (descriptor is ClassDescriptor && descriptor.isInner) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "inner class"))
trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "inner class"))
}
else if (isPrivateMemberOfExternalClass(descriptor)) {
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "private member of class"))
trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "private member of class"))
}
if (descriptor is ClassDescriptor && descriptor.kind != ClassKind.INTERFACE &&
descriptor.containingDeclaration.let { it is ClassDescriptor && it.kind == ClassKind.INTERFACE }
) {
diagnosticHolder.report(ErrorsJs.NESTED_CLASS_IN_EXTERNAL_INTERFACE.on(declaration))
trace.report(ErrorsJs.NESTED_CLASS_IN_EXTERNAL_INTERFACE.on(declaration))
}
if (descriptor !is PropertyAccessorDescriptor && descriptor.isExtension) {
@@ -74,7 +75,7 @@ object JsExternalChecker : SimpleDeclarationChecker {
is PropertyDescriptor -> "extension property"
else -> "extension member"
}
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, target))
trace.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, target))
}
if (descriptor is ClassDescriptor && descriptor.kind != ClassKind.ANNOTATION_CLASS) {
@@ -83,19 +84,19 @@ object JsExternalChecker : SimpleDeclarationChecker {
superClasses.removeAll { it.fqNameUnsafe == KotlinBuiltIns.FQ_NAMES._enum }
}
if (superClasses.any { !AnnotationsUtils.isNativeObject(it) && it.fqNameSafe != KotlinBuiltIns.FQ_NAMES.throwable }) {
diagnosticHolder.report(ErrorsJs.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE.on(declaration))
trace.report(ErrorsJs.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE.on(declaration))
}
}
if (descriptor is FunctionDescriptor && descriptor.isInline) {
diagnosticHolder.report(ErrorsJs.INLINE_EXTERNAL_DECLARATION.on(declaration))
trace.report(ErrorsJs.INLINE_EXTERNAL_DECLARATION.on(declaration))
}
if (descriptor is CallableMemberDescriptor && !(descriptor is PropertyAccessorDescriptor && descriptor.isDefault)) {
for (p in descriptor.valueParameters) {
if ((p.varargElementType ?: p.type).isExtensionFunctionType) {
val ktParam = p.source.getPsi() as? KtParameter ?: declaration
diagnosticHolder.report(ErrorsJs.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION.on(ktParam))
trace.report(ErrorsJs.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION.on(ktParam))
}
}
@@ -104,21 +105,21 @@ object JsExternalChecker : SimpleDeclarationChecker {
!(descriptor.getter?.isDefault ?: true && descriptor.setter?.isDefault ?: true)
if (!propertyWithCustomAccessors && descriptor.returnType?.isExtensionFunctionType ?: false) {
diagnosticHolder.report(ErrorsJs.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION.on(declaration))
trace.report(ErrorsJs.EXTENSION_FUNCTION_IN_EXTERNAL_DECLARATION.on(declaration))
}
}
if (descriptor is CallableMemberDescriptor && descriptor.isNonAbstractMemberOfInterface() &&
!descriptor.isNullableProperty()
) {
diagnosticHolder.report(ErrorsJs.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE.on(declaration))
trace.report(ErrorsJs.NON_ABSTRACT_MEMBER_OF_EXTERNAL_INTERFACE.on(declaration))
}
checkBody(declaration, descriptor, diagnosticHolder, bindingContext)
checkDelegation(declaration, descriptor, diagnosticHolder)
checkAnonymousInitializer(declaration, diagnosticHolder)
checkEnumEntry(declaration, diagnosticHolder)
checkConstructorPropertyParam(declaration, descriptor, diagnosticHolder)
checkBody(declaration, descriptor, trace, trace.bindingContext)
checkDelegation(declaration, descriptor, trace)
checkAnonymousInitializer(declaration, trace)
checkEnumEntry(declaration, trace)
checkConstructorPropertyParam(declaration, descriptor, trace)
}
private fun checkBody(
@@ -17,28 +17,22 @@
package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
object JsExternalFileChecker : SimpleDeclarationChecker {
object JsExternalFileChecker : DeclarationChecker {
private val annotationFqNames = setOf(AnnotationsUtils.JS_MODULE_ANNOTATION, AnnotationsUtils.JS_QUALIFIER_ANNOTATION)
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (!AnnotationsUtils.isNativeObject(descriptor) && DescriptorUtils.isTopLevelDeclaration(descriptor)) {
AnnotationsUtils.getContainingFileAnnotations(bindingContext, descriptor).asSequence()
.firstOrNull { it.fqName in annotationFqNames }
?.let {
diagnosticHolder.report(ErrorsJs.NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE.on(declaration, it.type))
}
AnnotationsUtils.getContainingFileAnnotations(context.trace.bindingContext, descriptor).asSequence()
.firstOrNull { it.fqName in annotationFqNames }
?.let {
context.trace.report(ErrorsJs.NON_EXTERNAL_DECLARATION_IN_INAPPROPRIATE_FILE.on(declaration, it.type))
}
}
}
}
@@ -21,40 +21,33 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
object JsInheritanceChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
object JsInheritanceChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor is FunctionDescriptor && !descriptor.isEffectivelyExternal() &&
isOverridingExternalWithOptionalParams(descriptor)
) {
diagnosticHolder.report(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS.on(declaration))
context.trace.report(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS.on(declaration))
}
else if (descriptor is ClassDescriptor && !descriptor.isEffectivelyExternal()) {
val fakeOverriddenMethod = findFakeMethodOverridingExternalWithOptionalParams(descriptor)
if (fakeOverriddenMethod != null) {
diagnosticHolder.report(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE.on(
declaration, fakeOverriddenMethod))
context.trace.report(ErrorsJs.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE.on(declaration, fakeOverriddenMethod))
}
}
if (descriptor is ClassDescriptor &&
descriptor.defaultType.immediateSupertypes().any { it.isBuiltinFunctionalTypeOrSubtype }
) {
diagnosticHolder.report(ErrorsJs.IMPLEMENTING_FUNCTION_INTERFACE.on(declaration as KtClassOrObject))
context.trace.report(ErrorsJs.IMPLEMENTING_FUNCTION_INTERFACE.on(declaration as KtClassOrObject))
}
}
@@ -19,55 +19,47 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
object JsModuleChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
checkSuperClass(bindingContext, diagnosticHolder, descriptor, declaration)
object JsModuleChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val trace = context.trace
checkSuperClass(declaration, descriptor, trace)
if (AnnotationsUtils.getModuleName(descriptor) == null && !AnnotationsUtils.isNonModule(descriptor)) return
if (descriptor is PropertyDescriptor && descriptor.isVar) {
diagnosticHolder.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_VAR.on(declaration))
trace.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_VAR.on(declaration))
}
if (!AnnotationsUtils.isNativeObject(descriptor)) {
diagnosticHolder.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_NON_NATIVE.on(declaration))
trace.report(ErrorsJs.JS_MODULE_PROHIBITED_ON_NON_NATIVE.on(declaration))
}
if (DescriptorUtils.isTopLevelDeclaration(descriptor)) {
val isFileModuleOrNonModule = AnnotationsUtils.getFileModuleName(bindingContext, descriptor) != null ||
AnnotationsUtils.isFromNonModuleFile(bindingContext, descriptor)
val isFileModuleOrNonModule = AnnotationsUtils.getFileModuleName(trace.bindingContext, descriptor) != null ||
AnnotationsUtils.isFromNonModuleFile(trace.bindingContext, descriptor)
if (isFileModuleOrNonModule) {
diagnosticHolder.report(ErrorsJs.NESTED_JS_MODULE_PROHIBITED.on(declaration))
trace.report(ErrorsJs.NESTED_JS_MODULE_PROHIBITED.on(declaration))
}
}
}
private fun checkSuperClass(
bindingContext: BindingContext,
diagnosticHolder: DiagnosticSink,
descriptor: DeclarationDescriptor,
declaration: KtDeclaration
) {
private fun checkSuperClass(declaration: KtDeclaration, descriptor: DeclarationDescriptor, trace: BindingTrace) {
if (descriptor !is ClassDescriptor) return
val superClass = descriptor.getSuperClassNotAny() ?: return
val psi = (declaration as KtClassOrObject).superTypeListEntries.firstOrNull { entry ->
bindingContext[BindingContext.TYPE, entry.typeReference]?.constructor?.declarationDescriptor == superClass
trace[BindingContext.TYPE, entry.typeReference]?.constructor?.declarationDescriptor == superClass
}
checkJsModuleUsage(bindingContext, diagnosticHolder, descriptor, superClass, psi ?: declaration)
checkJsModuleUsage(trace.bindingContext, trace, descriptor, superClass, psi ?: declaration)
}
}
@@ -19,31 +19,27 @@ package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
object JsMultipleInheritanceChecker : SimpleDeclarationChecker {
object JsMultipleInheritanceChecker : DeclarationChecker {
private val fqNames = listOf(
FqNameUnsafe("kotlin.CharSequence.get"),
FqNameUnsafe("kotlin.collections.CharIterator.nextChar")
)
private val simpleNames = fqNames.mapTo(mutableSetOf()) { it.shortName() }
override fun check(
declaration: KtDeclaration, descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
) {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor !is ClassDescriptor) return
for (callable in descriptor.unsubstitutedMemberScope.getContributedDescriptors { it in simpleNames }
.filterIsInstance<CallableMemberDescriptor>()) {
if (callable.overriddenDescriptors.size > 1 && callable.overriddenDescriptors.any { it.fqNameUnsafe in fqNames }) {
diagnosticHolder.report(ErrorsJs.WRONG_MULTIPLE_INHERITANCE.on(declaration, callable))
context.trace.report(ErrorsJs.WRONG_MULTIPLE_INHERITANCE.on(declaration, callable))
}
}
}
}
}
@@ -1,56 +1,25 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright 2000-2018 JetBrains s.r.o. 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.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.naming.NameSuggestion
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
class JsNameCharsChecker(private val suggestion: NameSuggestion) : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration, descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
) {
class JsNameCharsChecker(private val suggestion: NameSuggestion) : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (descriptor is PropertyAccessorDescriptor && AnnotationsUtils.getJsName(descriptor) == null) return
val suggestedName = suggestion.suggest(descriptor) ?: return
if (suggestedName.stable && suggestedName.names.any { NameSuggestion.sanitizeName(it) != it }) {
diagnosticHolder.report(ErrorsJs.NAME_CONTAINS_ILLEGAL_CHARS.on(declaration))
context.trace.report(ErrorsJs.NAME_CONTAINS_ILLEGAL_CHARS.on(declaration))
}
}
}
}
@@ -17,22 +17,21 @@
package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.js.PredefinedAnnotation
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.source.getPsi
object JsNameChecker : SimpleDeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext) {
object JsNameChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val trace = context.trace
if (descriptor is PropertyDescriptor) {
val namedAccessorCount = descriptor.accessors.count { AnnotationsUtils.getJsName(it) != null }
if (namedAccessorCount > 0 && namedAccessorCount < descriptor.accessors.size) {
diagnosticHolder.report(ErrorsJs.JS_NAME_IS_NOT_ON_ALL_ACCESSORS.on(declaration))
trace.report(ErrorsJs.JS_NAME_IS_NOT_ON_ALL_ACCESSORS.on(declaration))
}
}
@@ -40,29 +39,29 @@ object JsNameChecker : SimpleDeclarationChecker {
val jsNamePsi = jsName.source.getPsi() ?: declaration
if (AnnotationsUtils.getNameForAnnotatedObject(descriptor, PredefinedAnnotation.NATIVE) != null) {
diagnosticHolder.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_NAMED_NATIVE.on(jsNamePsi))
trace.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_NAMED_NATIVE.on(jsNamePsi))
}
if (descriptor is CallableMemberDescriptor && descriptor.overriddenDescriptors.isNotEmpty()) {
diagnosticHolder.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_OVERRIDE.on(jsNamePsi))
trace.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_OVERRIDE.on(jsNamePsi))
}
when (descriptor) {
is ConstructorDescriptor -> {
if (descriptor.isPrimary) {
diagnosticHolder.report(ErrorsJs.JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED.on(jsNamePsi))
trace.report(ErrorsJs.JS_NAME_ON_PRIMARY_CONSTRUCTOR_PROHIBITED.on(jsNamePsi))
}
}
is PropertyAccessorDescriptor -> {
if (AnnotationsUtils.getJsName(descriptor.correspondingProperty) != null) {
diagnosticHolder.report(ErrorsJs.JS_NAME_ON_ACCESSOR_AND_PROPERTY.on(jsNamePsi))
trace.report(ErrorsJs.JS_NAME_ON_ACCESSOR_AND_PROPERTY.on(jsNamePsi))
}
}
is PropertyDescriptor -> {
if (descriptor.isExtension) {
diagnosticHolder.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY.on(jsNamePsi))
trace.report(ErrorsJs.JS_NAME_PROHIBITED_FOR_EXTENSION_PROPERTY.on(jsNamePsi))
}
}
}
}
}
}
@@ -25,12 +25,13 @@ import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
import org.jetbrains.kotlin.resolve.scopes.MemberScope
class JsNameClashChecker(private val nameSuggestion: NameSuggestion) : SimpleDeclarationChecker {
class JsNameClashChecker(private val nameSuggestion: NameSuggestion) : DeclarationChecker {
companion object {
private val COMMON_DIAGNOSTICS = setOf(
Errors.REDECLARATION,
@@ -42,16 +43,11 @@ class JsNameClashChecker(private val nameSuggestion: NameSuggestion) : SimpleDec
private val clashedFakeOverrides = mutableMapOf<DeclarationDescriptor, Pair<DeclarationDescriptor, DeclarationDescriptor>>()
private val clashedDescriptors = mutableSetOf<Pair<DeclarationDescriptor, String>>()
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
// We don't generate JS properties for extension properties, we generate methods instead, so in this case
// check name clash only for accessors, not properties
if (!descriptor.isExtensionProperty) {
checkDescriptor(descriptor, declaration, diagnosticHolder, bindingContext)
checkDescriptor(descriptor, declaration, context.trace, context.trace.bindingContext)
}
}
@@ -196,4 +192,4 @@ class JsNameClashChecker(private val nameSuggestion: NameSuggestion) : SimpleDec
private fun presentsInGeneratedCode(descriptor: DeclarationDescriptor) =
!AnnotationsUtils.isNativeObject(descriptor) && !AnnotationsUtils.isLibraryObject(descriptor)
}
}
@@ -16,26 +16,19 @@
package org.jetbrains.kotlin.js.resolve.diagnostics
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
object JsRuntimeAnnotationChecker : SimpleDeclarationChecker {
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
object JsRuntimeAnnotationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
for ((annotationDescriptor, _) in descriptor.annotations.getAllAnnotations()) {
val annotationClass = annotationDescriptor.annotationClass ?: continue
if (annotationClass.getAnnotationRetention() != KotlinRetention.RUNTIME) continue
@@ -43,11 +36,11 @@ object JsRuntimeAnnotationChecker : SimpleDeclarationChecker {
val annotationPsi = (annotationDescriptor.source as? PsiSourceElement)?.psi ?: declaration
if (descriptor is MemberDescriptor && descriptor.isEffectivelyExternal()) {
diagnosticHolder.report(ErrorsJs.RUNTIME_ANNOTATION_ON_EXTERNAL_DECLARATION.on(annotationPsi))
context.trace.report(ErrorsJs.RUNTIME_ANNOTATION_ON_EXTERNAL_DECLARATION.on(annotationPsi))
}
else {
diagnosticHolder.report(ErrorsJs.RUNTIME_ANNOTATION_NOT_SUPPORTED.on(annotationPsi))
context.trace.report(ErrorsJs.RUNTIME_ANNOTATION_NOT_SUPPORTED.on(annotationPsi))
}
}
}
}
}
@@ -26,23 +26,18 @@ import org.jetbrains.kotlin.js.resolve.diagnostics.ErrorsJs
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
internal abstract class AbstractNativeAnnotationsChecker(private val requiredAnnotation: PredefinedAnnotation) : SimpleDeclarationChecker {
internal abstract class AbstractNativeAnnotationsChecker(private val requiredAnnotation: PredefinedAnnotation) : DeclarationChecker {
open fun additionalCheck(declaration: KtNamedFunction, descriptor: FunctionDescriptor, diagnosticHolder: DiagnosticSink) {}
override fun check(
declaration: KtDeclaration,
descriptor: DeclarationDescriptor,
diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext
) {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val annotationDescriptor = descriptor.annotations.findAnnotation(requiredAnnotation.fqName) ?: return
if (declaration !is KtNamedFunction || descriptor !is FunctionDescriptor) {
@@ -55,10 +50,10 @@ internal abstract class AbstractNativeAnnotationsChecker(private val requiredAnn
if (isMember && (isExtension || !AnnotationsUtils.isNativeObject(descriptor)) ||
!isMember && !isExtension
) {
diagnosticHolder.report(ErrorsJs.NATIVE_ANNOTATIONS_ALLOWED_ONLY_ON_MEMBER_OR_EXTENSION_FUN.on(declaration, annotationDescriptor.type))
context.trace.report(ErrorsJs.NATIVE_ANNOTATIONS_ALLOWED_ONLY_ON_MEMBER_OR_EXTENSION_FUN.on(declaration, annotationDescriptor.type))
}
additionalCheck(declaration, descriptor, diagnosticHolder)
additionalCheck(declaration, descriptor, context.trace)
}
}