KT-15677 KT-15775

Update parser & descriptor renderer to handle parenthesized types and function types properly.
Resolve annotations in parenthesized types.

AnnotationsImpl.isEmpty() returned false for targeted annotations only
(e.g., 'fun @receiver:Ann C?.foo()').
Properly keep track of targeted annotations.
This commit is contained in:
Dmitry Petrov
2017-01-13 16:29:40 +03:00
parent a429992e81
commit b9f9894310
45 changed files with 2094 additions and 67 deletions
@@ -163,6 +163,8 @@ public interface Errors {
DiagnosticFactory1<KtElement, KotlinType> EXPANDED_TYPE_CANNOT_BE_CONSTRUCTED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory1<KtTypeElement, KotlinType> EXPANDED_TYPE_CANNOT_BE_INHERITED = DiagnosticFactory1.create(ERROR);
DiagnosticFactory0<KtModifierList> MODIFIER_LIST_NOT_ALLOWED = DiagnosticFactory0.create(ERROR);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Errors in declarations
@@ -521,6 +521,8 @@ public class DefaultErrorMessages {
MAP.put(EXPANDED_TYPE_CANNOT_BE_CONSTRUCTED, "Expanded type {0} contains non-invariant projections in top-level arguments and cannot be constructed", RENDER_TYPE);
MAP.put(EXPANDED_TYPE_CANNOT_BE_INHERITED, "Expanded type {0} contains non-invariant projections in top-level arguments and cannot be inherited from", RENDER_TYPE);
MAP.put(MODIFIER_LIST_NOT_ALLOWED, "Modifiers and annotations are not allowed here, because there are other modifiers or annotations outside of parenthesis");
MAP.put(TOO_MANY_ARGUMENTS, "Too many arguments for {0}", FQ_NAMES_IN_TYPES);
MAP.put(CONSTANT_EXPECTED_TYPE_MISMATCH, "The {0} literal does not conform to the expected type {1}", STRING, RENDER_TYPE);
@@ -232,7 +232,7 @@ public interface KtTokens {
TokenSet TYPE_MODIFIER_KEYWORDS = TokenSet.create(SUSPEND_KEYWORD);
TokenSet TYPE_ARGUMENT_MODIFIER_KEYWORDS = TokenSet.create(IN_KEYWORD, OUT_KEYWORD);
TokenSet RESERVED_VALUE_PARAMETER_MODIFIER_KEYWORDS = TokenSet.create(OUT_KEYWORD, VARARG_KEYWORD); // lazy, out, ref
TokenSet RESERVED_VALUE_PARAMETER_MODIFIER_KEYWORDS = TokenSet.create(OUT_KEYWORD, VARARG_KEYWORD);
TokenSet VISIBILITY_MODIFIERS = TokenSet.create(PRIVATE_KEYWORD, PUBLIC_KEYWORD, INTERNAL_KEYWORD, PROTECTED_KEYWORD);
@@ -461,8 +461,8 @@ public class KotlinParsing extends AbstractKotlinParsing {
return doParseModifierList(tokenConsumer, MODIFIER_KEYWORDS, annotationParsingMode, noModifiersBefore);
}
private boolean parseValueParameterModifierList() {
return doParseModifierList(null, RESERVED_VALUE_PARAMETER_MODIFIER_KEYWORDS, DEFAULT, NO_MODIFIER_BEFORE_FOR_VALUE_PARAMETER);
private boolean parseFunctionTypeValueParameterModifierList() {
return doParseModifierList(null, RESERVED_VALUE_PARAMETER_MODIFIER_KEYWORDS, NO_ANNOTATIONS, NO_MODIFIER_BEFORE_FOR_VALUE_PARAMETER);
}
private boolean parseTypeModifierList() {
@@ -2196,7 +2196,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
if (isFunctionTypeContents) {
if (!tryParseValueParameter(typeRequired)) {
PsiBuilder.Marker valueParameter = mark();
parseValueParameterModifierList(); // lazy, out, ref
parseFunctionTypeValueParameterModifierList();
parseTypeRef();
closeDeclarationWithCommentBinders(valueParameter, VALUE_PARAMETER, false);
}
@@ -57,4 +57,16 @@ public class KtNullableType extends KtElementImplStub<KotlinPlaceHolderStub<KtNu
public KtTypeElement getInnerType() {
return KtStubbedPsiUtil.getStubOrPsiChild(this, KtStubElementTypes.TYPE_ELEMENT_TYPES, KtTypeElement.ARRAY_FACTORY);
}
@Nullable
public KtModifierList getModifierList() {
return getStubOrPsiChild(KtStubElementTypes.MODIFIER_LIST);
}
@NotNull
public List<KtAnnotationEntry> getAnnotationEntries() {
KtModifierList modifierList = getModifierList();
return modifierList != null ? modifierList.getAnnotationEntries()
: Collections.<KtAnnotationEntry>emptyList();
}
}
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.context.TypeLazinessToken
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations
import org.jetbrains.kotlin.descriptors.impl.VariableDescriptorImpl
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Errors.*
@@ -34,6 +35,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.codeFragmentUtil.debugTypeInfo
import org.jetbrains.kotlin.psi.codeFragmentUtil.suppressDiagnosticsInDebugMode
import org.jetbrains.kotlin.psi.debugText.getDebugText
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
import org.jetbrains.kotlin.resolve.PossiblyBareType.bare
import org.jetbrains.kotlin.resolve.PossiblyBareType.type
import org.jetbrains.kotlin.resolve.bindingContextUtil.recordScope
@@ -131,10 +133,10 @@ class TypeResolver(
}
private fun doResolvePossiblyBareType(c: TypeResolutionContext, typeReference: KtTypeReference): PossiblyBareType {
val annotations = annotationResolver.resolveAnnotationsWithoutArguments(c.scope, typeReference.getAnnotationEntries(), c.trace)
val typeElement = typeReference.typeElement
val annotations = resolveTypeAnnotations(c, typeReference)
val type = resolveTypeElement(c, annotations, typeReference.modifierList, typeElement)
c.trace.recordScope(c.scope, typeReference)
@@ -147,6 +149,29 @@ class TypeResolver(
return type
}
internal fun KtElementImplStub<*>.getAllModifierLists(): Array<out KtDeclarationModifierList> =
getStubOrPsiChildren(KtStubElementTypes.MODIFIER_LIST, KtStubElementTypes.MODIFIER_LIST.arrayFactory)
private fun resolveTypeAnnotations(c: TypeResolutionContext, modifierListsOwner: KtElementImplStub<*>): Annotations {
val modifierLists = modifierListsOwner.getAllModifierLists()
var result = Annotations.EMPTY
var isSplitModifierList = false
for (modifierList in modifierLists) {
if (isSplitModifierList) {
c.trace.report(MODIFIER_LIST_NOT_ALLOWED.on(modifierList))
}
val annotations = annotationResolver.resolveAnnotationsWithoutArguments(c.scope, modifierList.annotationEntries, c.trace)
result = composeAnnotations(result, annotations)
isSplitModifierList = true
}
return result
}
/**
* This function is light version of ForceResolveUtil.forceResolveAllContents
* We can't use ForceResolveUtil.forceResolveAllContents here because it runs ForceResolveUtil.forceResolveAllContents(getConstructor()),
@@ -176,12 +201,12 @@ class TypeResolver(
}
}
private fun resolveTypeElement(c: TypeResolutionContext, annotations: Annotations, modifiers: KtModifierList?, typeElement: KtTypeElement?): PossiblyBareType {
private fun resolveTypeElement(c: TypeResolutionContext, annotations: Annotations, outerModifierList: KtModifierList?, typeElement: KtTypeElement?): PossiblyBareType {
var result: PossiblyBareType? = null
val hasSuspendModifier = modifiers?.hasModifier(KtTokens.SUSPEND_KEYWORD) ?: false
val suspendModifier = modifiers?.getModifier(KtTokens.SUSPEND_KEYWORD)
if (hasSuspendModifier && typeElement !is KtFunctionType) {
val hasSuspendModifier = outerModifierList?.hasModifier(KtTokens.SUSPEND_KEYWORD) ?: false
val suspendModifier = outerModifierList?.getModifier(KtTokens.SUSPEND_KEYWORD)
if (hasSuspendModifier && !typeElement.canHaveFunctionTypeModifiers()) {
c.trace.report(Errors.WRONG_MODIFIER_TARGET.on(suspendModifier!!, KtTokens.SUSPEND_KEYWORD, "non-functional type"))
}
else if (hasSuspendModifier) {
@@ -208,8 +233,15 @@ class TypeResolver(
}
override fun visitNullableType(nullableType: KtNullableType) {
val innerType = nullableType.getInnerType()
val baseType = resolveTypeElement(c, annotations, modifiers, innerType)
val innerModifierList = nullableType.modifierList
if (innerModifierList != null && outerModifierList != null) {
c.trace.report(MODIFIER_LIST_NOT_ALLOWED.on(innerModifierList))
}
val innerAnnotations = composeAnnotations(annotations, resolveTypeAnnotations(c, nullableType))
val innerType = nullableType.innerType
val baseType = resolveTypeElement(c, innerAnnotations, outerModifierList ?: innerModifierList, innerType)
if (baseType.isNullable || innerType is KtNullableType || innerType is KtDynamicType) {
c.trace.report(REDUNDANT_NULLABLE.on(nullableType))
}
@@ -319,6 +351,9 @@ class TypeResolver(
return result ?: type(ErrorUtils.createErrorType(typeElement?.getDebugText() ?: "No type element"))
}
private fun KtTypeElement?.canHaveFunctionTypeModifiers(): Boolean =
this is KtFunctionType
private fun resolveTypeForTypeParameter(
c: TypeResolutionContext, annotations: Annotations,
typeParameter: TypeParameterDescriptor,