Support non-parenthesized annotations on functional types without receiver
^KT-31734 Fixed
This commit is contained in:
@@ -268,6 +268,8 @@ public interface Errors {
|
||||
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_UNSIGNED_LITERALS = DiagnosticFactory1.create(WARNING);
|
||||
DiagnosticFactory1<PsiElement, FqName> EXPERIMENTAL_UNSIGNED_LITERALS_ERROR = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<PsiElement> NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
// Const
|
||||
DiagnosticFactory0<PsiElement> CONST_VAL_NOT_TOP_LEVEL_OR_OBJECT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<PsiElement> CONST_VAL_WITH_GETTER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
+2
@@ -159,6 +159,8 @@ public class DefaultErrorMessages {
|
||||
MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS, "Unsigned literals are experimental and their usages should be marked with ''@{0}'' or ''@UseExperimental({0}::class)''", TO_STRING);
|
||||
MAP.put(EXPERIMENTAL_UNSIGNED_LITERALS_ERROR, "Unsigned literals are experimental and their usages must be marked with ''@{0}'' or ''@UseExperimental({0}::class)''", TO_STRING);
|
||||
|
||||
MAP.put(NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES, "Non parenthesized annotations on function types without receiver isn't yet supported (see KT-31734 for details)");
|
||||
|
||||
MAP.put(REDUNDANT_MODIFIER, "Modifier ''{0}'' is redundant because ''{1}'' is present", TO_STRING, TO_STRING);
|
||||
MAP.put(REDUNDANT_OPEN_IN_INTERFACE, "Modifier 'open' is redundant for abstract interface members");
|
||||
MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter");
|
||||
|
||||
@@ -34,6 +34,9 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
|
||||
import org.jetbrains.kotlin.psi.debugText.getDebugText
|
||||
import org.jetbrains.kotlin.psi.psiUtil.checkReservedYield
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getPrevSiblingIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.psi.psiUtil.hasSuspendModifier
|
||||
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
|
||||
import org.jetbrains.kotlin.resolve.PossiblyBareType.bare
|
||||
import org.jetbrains.kotlin.resolve.PossiblyBareType.type
|
||||
@@ -69,6 +72,9 @@ class TypeResolver(
|
||||
private val platformToKotlinClassMap: PlatformToKotlinClassMap,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
private val isNonParenthesizedAnnotationsOnFunctionalTypesEnabled =
|
||||
languageVersionSettings.getFeatureSupport(LanguageFeature.NonParenthesizedAnnotationsOnFunctionalTypes) == LanguageFeature.State.ENABLED
|
||||
|
||||
open class TypeTransformerForTests {
|
||||
open fun transformType(kotlinType: KotlinType): KotlinType? = null
|
||||
}
|
||||
@@ -129,12 +135,53 @@ class TypeResolver(
|
||||
internal fun KtElementImplStub<*>.getAllModifierLists(): Array<out KtDeclarationModifierList> =
|
||||
getStubOrPsiChildren(KtStubElementTypes.MODIFIER_LIST, KtStubElementTypes.MODIFIER_LIST.arrayFactory)
|
||||
|
||||
// TODO: remove this method and its usages in 1.4
|
||||
private fun checkNonParenthesizedAnnotationsOnFunctionalType(
|
||||
typeElement: KtFunctionType,
|
||||
annotationEntries: List<KtAnnotationEntry>,
|
||||
trace: BindingTrace
|
||||
) {
|
||||
val lastAnnotationEntry = annotationEntries.lastOrNull()
|
||||
val isAnnotationsGroupedUsingBrackets =
|
||||
lastAnnotationEntry?.getNextSiblingIgnoringWhitespaceAndComments()?.node?.elementType == KtTokens.RBRACKET
|
||||
val hasAnnotationParentheses = lastAnnotationEntry?.valueArgumentList != null
|
||||
val isFunctionalTypeStartingWithParentheses = typeElement.firstChild is KtParameterList
|
||||
val hasSuspendModifierBeforeParentheses =
|
||||
typeElement.getPrevSiblingIgnoringWhitespaceAndComments().run { this is KtDeclarationModifierList && hasSuspendModifier() }
|
||||
|
||||
if (lastAnnotationEntry != null &&
|
||||
isFunctionalTypeStartingWithParentheses &&
|
||||
!hasAnnotationParentheses &&
|
||||
!isAnnotationsGroupedUsingBrackets &&
|
||||
!hasSuspendModifierBeforeParentheses
|
||||
) {
|
||||
trace.report(Errors.NON_PARENTHESIZED_ANNOTATIONS_ON_FUNCTIONAL_TYPES.on(lastAnnotationEntry))
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveTypeAnnotations(c: TypeResolutionContext, modifierListsOwner: KtElementImplStub<*>): Annotations {
|
||||
val modifierLists = modifierListsOwner.getAllModifierLists()
|
||||
|
||||
var result = Annotations.EMPTY
|
||||
var isSplitModifierList = false
|
||||
|
||||
if (!isNonParenthesizedAnnotationsOnFunctionalTypesEnabled) {
|
||||
val targetType = when (modifierListsOwner) {
|
||||
is KtNullableType -> modifierListsOwner.innerType
|
||||
is KtTypeReference -> modifierListsOwner.typeElement
|
||||
else -> null
|
||||
}
|
||||
val annotationEntries = when (modifierListsOwner) {
|
||||
is KtNullableType -> modifierListsOwner.modifierList?.annotationEntries
|
||||
is KtTypeReference -> modifierListsOwner.annotationEntries
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (targetType is KtFunctionType && annotationEntries != null) {
|
||||
checkNonParenthesizedAnnotationsOnFunctionalType(targetType, annotationEntries, c.trace)
|
||||
}
|
||||
}
|
||||
|
||||
for (modifierList in modifierLists) {
|
||||
if (isSplitModifierList) {
|
||||
c.trace.report(MODIFIER_LIST_NOT_ALLOWED.on(modifierList))
|
||||
|
||||
Reference in New Issue
Block a user