KT-11588 Type aliases

Resolution & expansion for type aliases.
NB: Nested type aliases capturing type parameters of outer classes are not supported yet.
This commit is contained in:
Dmitry Petrov
2016-04-26 15:25:31 +03:00
parent ec94893189
commit a4406687f1
46 changed files with 919 additions and 56 deletions
@@ -16,8 +16,8 @@
package org.jetbrains.kotlin.cli.jvm.repl
import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.lazy.declarations.PackageMemberDeclarationProvider
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
open class DelegatePackageMemberDeclarationProvider(var delegate: PackageMemberDeclarationProvider) : PackageMemberDeclarationProvider {
@@ -35,4 +35,6 @@ open class DelegatePackageMemberDeclarationProvider(var delegate: PackageMemberD
override fun getPropertyDeclarations(name: Name) = delegate.getPropertyDeclarations(name)
override fun getClassOrObjectDeclarations(name: Name) = delegate.getClassOrObjectDeclarations(name)
override fun getTypeAliasDeclarations(name: Name) = delegate.getTypeAliasDeclarations(name)
}
@@ -115,6 +115,11 @@ public interface Errors {
DiagnosticFactory0<KtParameter> REIFIED_TYPE_IN_CATCH_CLAUSE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeParameterList> GENERIC_THROWABLE_SUBCLASS = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<KtUserType, ClassifierDescriptor> RECURSIVE_TYPEALIAS_EXPANSION = DiagnosticFactory1.create(ERROR);
DiagnosticFactory3<KtUserType, KotlinType, KotlinType, ClassifierDescriptor> UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION =
DiagnosticFactory3.create(ERROR);
DiagnosticFactory1<KtUserType, KotlinType> CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION = DiagnosticFactory1.create(ERROR);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Errors in declarations
@@ -281,8 +286,8 @@ public interface Errors {
DiagnosticFactory2<KtSimpleNameExpression, KtTypeConstraint, KtTypeParameterListOwner> NAME_IN_CONSTRAINT_IS_NOT_A_TYPE_PARAMETER =
DiagnosticFactory2.create(ERROR);
DiagnosticFactory0<KtTypeParameter>
VARIANCE_ON_TYPE_PARAMETER_OF_FUNCTION_OR_PROPERTY = DiagnosticFactory0.create(ERROR, VARIANCE_MODIFIER);
DiagnosticFactory0<KtTypeParameter> VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED = DiagnosticFactory0.create(ERROR, VARIANCE_MODIFIER);
DiagnosticFactory0<KtTypeReference> BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeParameterList> DEPRECATED_TYPE_PARAMETER_SYNTAX = DiagnosticFactory0.create(ERROR);
@@ -413,6 +413,13 @@ public class DefaultErrorMessages {
MAP.put(USELESS_ELVIS_ON_LAMBDA_EXPRESSION, "Left operand of elvis operator (?:) is a lambda expression");
MAP.put(CONFLICTING_UPPER_BOUNDS, "Upper bounds of {0} have empty intersection", NAME);
MAP.put(RECURSIVE_TYPEALIAS_EXPANSION, "Recursive type alias in expansion: {0}", NAME);
MAP.put(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION,
"Type argument resulting from type alias expansion is not within required bounds for ''{2}'': " +
"should be subtype of ''{0}'', substituted type is ''{1}''",
RENDER_TYPE, RENDER_TYPE, NAME);
MAP.put(CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION, "Conflicting projection in type alias expansion in intermediate type ''{0}''", RENDER_TYPE);
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);
@@ -503,7 +510,8 @@ public class DefaultErrorMessages {
MAP.put(MISSING_CONSTRUCTOR_KEYWORD, "Use 'constructor' keyword after modifiers of primary constructor");
MAP.put(VARIANCE_ON_TYPE_PARAMETER_OF_FUNCTION_OR_PROPERTY, "Variance annotations are only allowed for type parameters of classes and interfaces");
MAP.put(VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED, "Variance annotations are only allowed for type parameters of classes and interfaces");
MAP.put(BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED, "Bounds are not allowed on type alias parameters");
MAP.put(DEPRECATED_TYPE_PARAMETER_SYNTAX, "Type parameters must be placed before the name of the function");
@@ -216,10 +216,11 @@ public interface BindingContext {
WritableSlice<KtParameter, VariableDescriptor> VALUE_PARAMETER = Slices.createSimpleSlice();
WritableSlice<KtPropertyAccessor, PropertyAccessorDescriptor> PROPERTY_ACCESSOR = Slices.createSimpleSlice();
WritableSlice<PsiElement, PropertyDescriptor> PRIMARY_CONSTRUCTOR_PARAMETER = Slices.createSimpleSlice();
WritableSlice<KtTypeAlias, TypeAliasDescriptor> TYPE_ALIAS = Slices.createSimpleSlice();
WritableSlice[] DECLARATIONS_TO_DESCRIPTORS = new WritableSlice[] {
CLASS, TYPE_PARAMETER, FUNCTION, CONSTRUCTOR, VARIABLE, VALUE_PARAMETER, PROPERTY_ACCESSOR,
PRIMARY_CONSTRUCTOR_PARAMETER, SCRIPT
PRIMARY_CONSTRUCTOR_PARAMETER, SCRIPT, TYPE_ALIAS
};
@SuppressWarnings("unchecked")
@@ -20,10 +20,7 @@ import org.jetbrains.annotations.Mutable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes;
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor;
import org.jetbrains.kotlin.descriptors.PropertyDescriptor;
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor;
@@ -49,6 +46,8 @@ public interface BodiesResolveContext {
Map<KtProperty, PropertyDescriptor> getProperties();
@Mutable
Map<KtNamedFunction, SimpleFunctionDescriptor> getFunctions();
@Mutable
Map<KtTypeAlias, TypeAliasDescriptor> getTypeAliases();
@Nullable
LexicalScope getDeclaringScope(@NotNull KtDeclaration declaration);
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
import org.jetbrains.kotlin.resolve.dataClassUtils.DataClassUtilsKt;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.lazy.descriptors.TypeAliasDescriptorImpl;
import org.jetbrains.kotlin.resolve.scopes.*;
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
@@ -62,6 +63,7 @@ import static org.jetbrains.kotlin.diagnostics.Errors.*;
import static org.jetbrains.kotlin.lexer.KtTokens.*;
import static org.jetbrains.kotlin.resolve.BindingContext.CONSTRUCTOR;
import static org.jetbrains.kotlin.resolve.BindingContext.PACKAGE_TO_FILES;
import static org.jetbrains.kotlin.resolve.BindingContext.TYPE_ALIAS;
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveModalityFromModifiers;
import static org.jetbrains.kotlin.resolve.ModifiersChecker.resolveVisibilityFromModifiers;
@@ -388,24 +390,29 @@ public class DescriptorResolver {
return builtIns.getArrayType(Variance.OUT_VARIANCE, elementType);
}
public List<TypeParameterDescriptorImpl> resolveTypeParametersForCallableDescriptor(
public List<TypeParameterDescriptorImpl> resolveTypeParametersForDescriptor(
DeclarationDescriptor containingDescriptor,
LexicalWritableScope extensibleScope,
LexicalScope scopeForAnnotationsResolve,
List<KtTypeParameter> typeParameters,
BindingTrace trace
) {
assert containingDescriptor instanceof FunctionDescriptor ||
containingDescriptor instanceof PropertyDescriptor ||
containingDescriptor instanceof TypeAliasDescriptor
: "This method should be called for functions, properties, or type aliases, got " + containingDescriptor;
List<TypeParameterDescriptorImpl> result = new ArrayList<TypeParameterDescriptorImpl>();
for (int i = 0, typeParametersSize = typeParameters.size(); i < typeParametersSize; i++) {
KtTypeParameter typeParameter = typeParameters.get(i);
result.add(resolveTypeParameterForCallableDescriptor(
result.add(resolveTypeParameterForDescriptor(
containingDescriptor, extensibleScope, scopeForAnnotationsResolve, typeParameter, i, trace));
}
return result;
}
private TypeParameterDescriptorImpl resolveTypeParameterForCallableDescriptor(
DeclarationDescriptor containingDescriptor,
private TypeParameterDescriptorImpl resolveTypeParameterForDescriptor(
final DeclarationDescriptor containingDescriptor,
LexicalWritableScope extensibleScope,
LexicalScope scopeForAnnotationsResolve,
final KtTypeParameter typeParameter,
@@ -413,8 +420,7 @@ public class DescriptorResolver {
final BindingTrace trace
) {
if (typeParameter.getVariance() != Variance.INVARIANT) {
assert !(containingDescriptor instanceof ClassifierDescriptor) : "This method is intended for functions/properties";
trace.report(VARIANCE_ON_TYPE_PARAMETER_OF_FUNCTION_OR_PROPERTY.on(typeParameter));
trace.report(VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED.on(typeParameter));
}
Annotations annotations =
@@ -431,7 +437,9 @@ public class DescriptorResolver {
new Function1<KotlinType, Void>() {
@Override
public Void invoke(KotlinType type) {
trace.report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeParameter));
if (!(containingDescriptor instanceof TypeAliasDescriptor)) {
trace.report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(typeParameter));
}
return null;
}
},
@@ -667,6 +675,65 @@ public class DescriptorResolver {
return variableDescriptor;
}
@NotNull
public TypeAliasDescriptor resolveTypeAliasDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@NotNull LexicalScope scope,
@NotNull KtTypeAlias typeAlias,
@NotNull final BindingTrace trace
) {
KtModifierList modifierList = typeAlias.getModifierList();
Visibility visibility = resolveVisibilityFromModifiers(typeAlias, getDefaultVisibility(typeAlias, containingDeclaration));
Annotations allAnnotations = annotationResolver.resolveAnnotationsWithArguments(scope, modifierList, trace);
Name name = KtPsiUtil.safeName(typeAlias.getName());
SourceElement sourceElement = KotlinSourceElementKt.toSourceElement(typeAlias);
TypeAliasDescriptorImpl typeAliasDescriptor = TypeAliasDescriptorImpl.create(
containingDeclaration, allAnnotations, name, sourceElement, visibility);
List<TypeParameterDescriptorImpl> typeParameterDescriptors;
final LexicalScope scopeWithTypeParameters;
{
List<KtTypeParameter> typeParameters = typeAlias.getTypeParameters();
if (typeParameters.isEmpty()) {
scopeWithTypeParameters = scope;
typeParameterDescriptors = Collections.emptyList();
}
else {
LexicalWritableScope writableScope = new LexicalWritableScope(
scope, containingDeclaration, false, null, new TraceBasedLocalRedeclarationChecker(trace),
LexicalScopeKind.TYPE_ALIAS_HEADER);
typeParameterDescriptors = resolveTypeParametersForDescriptor(
typeAliasDescriptor, writableScope, scope, typeParameters, trace);
writableScope.freeze();
checkNoGenericBoundsOnTypeAliasParameters(typeAlias, trace);
resolveGenericBounds(typeAlias, typeAliasDescriptor, writableScope, typeParameterDescriptors, trace);
scopeWithTypeParameters = writableScope;
}
}
final KtTypeReference typeReference = typeAlias.getTypeReference();
typeAliasDescriptor.initialize(typeParameterDescriptors, storageManager.createLazyValue(new Function0<KotlinType>() {
@Override
public KotlinType invoke() {
return typeResolver.resolveAbbreviatedType(scopeWithTypeParameters, typeReference, trace, true);
}
}));
trace.record(TYPE_ALIAS, typeAlias, typeAliasDescriptor);
return typeAliasDescriptor;
}
private static void checkNoGenericBoundsOnTypeAliasParameters(@NotNull KtTypeAlias typeAlias, @NotNull BindingTrace trace) {
for (KtTypeParameter typeParameter : typeAlias.getTypeParameters()) {
KtTypeReference bound = typeParameter.getExtendsBound();
if (bound != null) {
trace.report(BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED.on(bound));
}
}
}
@NotNull
public PropertyDescriptor resolvePropertyDescriptor(
@NotNull DeclarationDescriptor containingDeclaration,
@@ -727,7 +794,7 @@ public class DescriptorResolver {
LexicalWritableScope writableScope = new LexicalWritableScope(
scope, containingDeclaration, false, null, new TraceBasedLocalRedeclarationChecker(trace, overloadChecker),
LexicalScopeKind.PROPERTY_HEADER);
typeParameterDescriptors = resolveTypeParametersForCallableDescriptor(
typeParameterDescriptors = resolveTypeParametersForDescriptor(
propertyDescriptor, writableScope, scope, typeParameters, trace);
writableScope.freeze();
resolveGenericBounds(property, propertyDescriptor, writableScope, typeParameterDescriptors, trace);
@@ -1092,6 +1159,27 @@ public class DescriptorResolver {
}
}
public static void checkBoundsInTypeAlias(
@NotNull KtUserType typeAliasElement,
@NotNull KotlinType typeArgument,
@NotNull TypeParameterDescriptor typeParameterDescriptor,
@NotNull TypeSubstitutor substitutor,
@NotNull BindingTrace trace
) {
DeclarationDescriptor containingDeclaration = typeParameterDescriptor.getContainingDeclaration();
assert containingDeclaration instanceof ClassifierDescriptor :
"Containing declaration of a type parameter should be a classifier, got " + containingDeclaration;
ClassifierDescriptor containingClassifier = (ClassifierDescriptor) containingDeclaration;
for (KotlinType bound : typeParameterDescriptor.getUpperBounds()) {
KotlinType substitutedBound = substitutor.safeSubstitute(bound, Variance.INVARIANT);
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(typeArgument, substitutedBound)) {
trace.report(UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION.on(
typeAliasElement, substitutedBound, typeArgument, containingClassifier));
}
}
}
public static boolean checkHasOuterClassInstance(
@NotNull LexicalScope scope,
@NotNull BindingTrace trace,
@@ -146,7 +146,7 @@ class FunctionDescriptorResolver(
TraceBasedLocalRedeclarationChecker(trace, overloadChecker), LexicalScopeKind.FUNCTION_HEADER)
val typeParameterDescriptors = descriptorResolver.
resolveTypeParametersForCallableDescriptor(functionDescriptor, innerScope, scope, function.typeParameters, trace)
resolveTypeParametersForDescriptor(functionDescriptor, innerScope, scope, function.typeParameters, trace)
descriptorResolver.resolveGenericBounds(function, functionDescriptor, innerScope, typeParameterDescriptors, trace)
val receiverTypeRef = function.receiverTypeReference
@@ -54,6 +54,7 @@ class LazyTopDownAnalyzer(
val properties = ArrayList<KtProperty>()
val functions = ArrayList<KtNamedFunction>()
val typeAliases = ArrayList<KtTypeAlias>()
// fill in the context
for (declaration in declarations) {
@@ -168,6 +169,10 @@ class LazyTopDownAnalyzer(
override fun visitProperty(property: KtProperty) {
properties.add(property)
}
override fun visitTypeAlias(typeAlias: KtTypeAlias) {
typeAliases.add(typeAlias)
}
})
}
@@ -175,6 +180,8 @@ class LazyTopDownAnalyzer(
createPropertyDescriptors(c, topLevelFqNames, properties)
createTypeAliasDescriptors(c, topLevelFqNames, typeAliases)
resolveAllHeadersInClasses(c)
declarationResolver.checkRedeclarationsInPackages(topLevelDescriptorProvider, topLevelFqNames)
@@ -199,6 +206,16 @@ class LazyTopDownAnalyzer(
}
}
private fun createTypeAliasDescriptors(c: TopDownAnalysisContext, topLevelFqNames: Multimap<FqName, KtElement>, typeAliases: List<KtTypeAlias>) {
for (typeAlias in typeAliases) {
val descriptor = lazyDeclarationResolver.resolveToDescriptor(typeAlias) as TypeAliasDescriptor
c.typeAliases[typeAlias] = descriptor
ForceResolveUtil.forceResolveAllContents(descriptor.annotations)
registerTopLevelFqName(topLevelFqNames, typeAlias, descriptor)
}
}
private fun createPropertyDescriptors(c: TopDownAnalysisContext, topLevelFqNames: Multimap<FqName, KtElement>, properties: List<KtProperty>) {
for (property in properties) {
val descriptor = lazyDeclarationResolver.resolveToDescriptor(property) as PropertyDescriptor
@@ -370,8 +370,10 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
val nextPackageOrClassDescriptor =
when (currentDescriptor) {
is TypeAliasDescriptor -> // TODO type aliases as qualifiers? (would break some assumptions in TypeResolver)
currentDescriptor.underlyingClassDescriptor.getContributedClassifier(qualifierPart)
is ClassDescriptor ->
currentDescriptor.unsubstitutedInnerClassesScope.getContributedClassifier(qualifierPart.name, qualifierPart.location)
currentDescriptor.getContributedClassifier(qualifierPart)
is PackageViewDescriptor -> {
val packageView =
if (qualifierPart.typeArguments == null) {
@@ -404,6 +406,9 @@ class QualifiedExpressionResolver(val symbolUsageValidator: SymbolUsageValidator
return Pair(currentDescriptor, path.size)
}
fun ClassDescriptor.getContributedClassifier(qualifierPart: QualifierPart) =
unsubstitutedInnerClassesScope.getContributedClassifier(qualifierPart.name, qualifierPart.location)
fun resolveNameExpressionAsQualifierForDiagnostics(
expression: KtSimpleNameExpression,
receiver: Receiver?,
@@ -45,6 +45,7 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
private final Map<KtNamedFunction, SimpleFunctionDescriptor> functions = Maps.newLinkedHashMap();
private final Map<KtProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap();
private final Map<KtParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap();
private final Map<KtTypeAlias, TypeAliasDescriptor> typeAliases = Maps.newLinkedHashMap();
private Map<KtCallableDeclaration, CallableMemberDescriptor> members = null;
private final Map<KtScript, LazyScriptDescriptor> scripts = Maps.newLinkedHashMap();
@@ -139,6 +140,11 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
return functions;
}
@Override
public Map<KtTypeAlias, TypeAliasDescriptor> getTypeAliases() {
return typeAliases;
}
@NotNull
public Map<KtCallableDeclaration, CallableMemberDescriptor> getMembers() {
if (members == null) {
@@ -26,9 +26,14 @@ public class TypeResolutionContext {
public final boolean allowBareTypes;
public final boolean forceResolveLazyTypes;
public final boolean isDebuggerContext;
public final boolean abbreviated;
public TypeResolutionContext(@NotNull LexicalScope scope, @NotNull BindingTrace trace, boolean checkBounds, boolean allowBareTypes, boolean isDebuggerContext) {
this(scope, trace, checkBounds, allowBareTypes, allowBareTypes, isDebuggerContext);
this(scope, trace, checkBounds, allowBareTypes, allowBareTypes, isDebuggerContext, false);
}
public TypeResolutionContext(@NotNull LexicalScope scope, @NotNull BindingTrace trace, boolean checkBounds, boolean allowBareTypes, boolean isDebuggerContext, boolean abbreviated) {
this(scope, trace, checkBounds, allowBareTypes, allowBareTypes, isDebuggerContext, abbreviated);
}
private TypeResolutionContext(
@@ -37,7 +42,8 @@ public class TypeResolutionContext {
boolean checkBounds,
boolean allowBareTypes,
boolean forceResolveLazyTypes,
boolean isDebuggerContext
boolean isDebuggerContext,
boolean abbreviated
) {
this.scope = scope;
this.trace = trace;
@@ -45,9 +51,10 @@ public class TypeResolutionContext {
this.allowBareTypes = allowBareTypes;
this.forceResolveLazyTypes = forceResolveLazyTypes;
this.isDebuggerContext = isDebuggerContext;
this.abbreviated = abbreviated;
}
public TypeResolutionContext noBareTypes() {
return new TypeResolutionContext(scope, trace, checkBounds, false, forceResolveLazyTypes, isDebuggerContext);
return new TypeResolutionContext(scope, trace, checkBounds, false, forceResolveLazyTypes, isDebuggerContext, abbreviated);
}
}
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.Variance.*
import org.jetbrains.kotlin.types.typeUtil.isArrayOfNothing
import java.util.*
class TypeResolver(
private val annotationResolver: AnnotationResolver,
@@ -64,7 +65,11 @@ class TypeResolver(
fun resolveType(scope: LexicalScope, typeReference: KtTypeReference, trace: BindingTrace, checkBounds: Boolean): KotlinType {
// bare types are not allowed
return resolveType(TypeResolutionContext(scope, trace, checkBounds, false, typeReference.suppressDiagnosticsInDebugMode()), typeReference)
return resolveType(TypeResolutionContext(scope, trace, checkBounds, false, typeReference.suppressDiagnosticsInDebugMode(), false), typeReference)
}
fun resolveAbbreviatedType(scope: LexicalScope, typeReference: KtTypeReference, trace: BindingTrace, checkBounds: Boolean): KotlinType {
return resolveType(TypeResolutionContext(scope, trace, checkBounds, false, typeReference.suppressDiagnosticsInDebugMode(), true), typeReference)
}
private fun resolveType(c: TypeResolutionContext, typeReference: KtTypeReference): KotlinType {
@@ -181,7 +186,10 @@ class TypeResolver(
type(resolveTypeForTypeParameter(c, annotations, classifierDescriptor, referenceExpression, type))
}
is ClassDescriptor -> resolveTypeForClass(c, annotations, classifierDescriptor, type, qualifierResolutionResults)
is ClassDescriptor ->
resolveTypeForClass(c, annotations, classifierDescriptor, type, qualifierResolutionResults)
is TypeAliasDescriptor ->
resolveTypeForTypeAlias(c, annotations, classifierDescriptor, type, qualifierResolutionResults)
else -> error("Unexpected classifier type: ${classifierDescriptor.javaClass}")
}
}
@@ -347,7 +355,7 @@ class TypeResolver(
}
if (ErrorUtils.isError(classDescriptor)) {
return createErrorTypeAndResolveArguments(c, projectionFromAllQualifierParts, "[Error type: $typeConstructor]")
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeConstructor)
}
val collectedArgumentAsTypeProjections =
@@ -393,6 +401,264 @@ class TypeResolver(
return type(resultingType)
}
private fun resolveTypeForTypeAlias(
c: TypeResolutionContext,
annotations: Annotations,
typeAliasDescriptor: TypeAliasDescriptor,
type: KtUserType,
qualifierResolutionResult: QualifiedExpressionResolver.TypeQualifierResolutionResult
): PossiblyBareType {
val typeAliasConstructor = typeAliasDescriptor.typeConstructor
val projectionFromAllQualifierParts = qualifierResolutionResult.allProjections
if (ErrorUtils.isError(typeAliasDescriptor)) {
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeAliasConstructor)
}
// TODO type arguments substitution for type parameters of outer classes
// TODO should we support type aliases as qualifiers? what about generics?
val typeAliasParameters = typeAliasDescriptor.declaredTypeParameters
val typeAliasQualifierPart = qualifierResolutionResult.qualifierParts.lastOrNull()
?: return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeAliasConstructor)
// TODO appendDefaultArgumentsForInnerScope
val typeAliasArguments = typeAliasQualifierPart.typeArguments?.arguments.orEmpty()
if (typeAliasParameters.size != typeAliasArguments.size) {
c.trace.report(WRONG_NUMBER_OF_TYPE_ARGUMENTS.on(typeAliasQualifierPart.typeArguments ?: typeAliasQualifierPart.expression,
typeAliasParameters.size, typeAliasDescriptor))
return createErrorTypeForTypeConstructor(c, projectionFromAllQualifierParts, typeAliasConstructor)
}
return if (c.abbreviated) {
val arguments = resolveTypeProjections(c, typeAliasDescriptor.typeConstructor, typeAliasArguments)
val abbreviatedType = KotlinTypeImpl.create(annotations, typeAliasDescriptor.typeConstructor, false, arguments, MemberScope.Empty)
type(abbreviatedType)
}
else {
val typeAliasExpansion = createTypeAliasExpansionFromSource(c, type, typeAliasDescriptor, typeAliasArguments)
val expandedType = expandTypeAlias(c, typeAliasExpansion, annotations)
type(expandedType)
}
}
private class AbbreviatedTypeImpl(override val abbreviatedType: KotlinType): AbbreviatedType
private fun withAbbreviatedType(abbreviatedType: KotlinType): TypeCapabilities =
SingletonTypeCapabilities(AbbreviatedType::class.java, AbbreviatedTypeImpl(abbreviatedType))
private class TypeAliasExpansionContext(
val element: KtUserType,
val argumentElements: Map<TypeParameterDescriptor, KtTypeProjection>
)
private class TypeAliasExpansion(
val context: TypeAliasExpansionContext,
val parent: TypeAliasExpansion?,
val descriptor: TypeAliasDescriptor,
val arguments: List<TypeProjection>,
val mapping: Map<TypeParameterDescriptor, TypeProjection>
) {
fun getReplacement(constructor: TypeConstructor): TypeProjection? {
val descriptor = constructor.declarationDescriptor
return if (descriptor is TypeParameterDescriptor)
mapping[descriptor]
else
null
}
fun isRecursion(descriptor: TypeAliasDescriptor): Boolean =
this.descriptor == descriptor || (parent?.isRecursion(descriptor) ?: false)
}
private fun createTypeAliasExpansionFromSource(
c: TypeResolutionContext,
element: KtUserType,
descriptor: TypeAliasDescriptor,
argumentElements: List<KtTypeProjection>
): TypeAliasExpansion {
val typeAliasParameters = descriptor.typeConstructor.parameters
val arguments = resolveTypeProjections(c, descriptor.typeConstructor, argumentElements)
val mappedArguments: Map<TypeParameterDescriptor, TypeProjection>
val mappedElements: Map<TypeParameterDescriptor, KtTypeProjection>
if (typeAliasParameters.isNotEmpty()) {
val resultingArguments = HashMap<TypeParameterDescriptor, TypeProjection>()
val resultingElements = HashMap<TypeParameterDescriptor, KtTypeProjection>()
typeAliasParameters.forEachIndexed { i, typeParameterDescriptor ->
resultingArguments[typeParameterDescriptor] = arguments[i]
resultingElements[typeParameterDescriptor] = argumentElements[i]
}
mappedArguments = resultingArguments
mappedElements = resultingElements
}
else {
mappedArguments = emptyMap()
mappedElements = emptyMap()
}
return TypeAliasExpansion(TypeAliasExpansionContext(element, mappedElements), null, descriptor, arguments, mappedArguments)
}
private fun createNestedTypeAliasExpansion(
parent: TypeAliasExpansion,
typeAliasDescriptor: TypeAliasDescriptor,
expandedArguments: List<TypeProjection>
): TypeAliasExpansion {
val mappedArguments = HashMap<TypeParameterDescriptor, TypeProjection>()
typeAliasDescriptor.typeConstructor.parameters.forEachIndexed { i, typeParameterDescriptor ->
mappedArguments[typeParameterDescriptor] = expandedArguments[i]
}
return TypeAliasExpansion(parent.context, parent, typeAliasDescriptor, expandedArguments, mappedArguments)
}
private fun expandTypeAlias(
c: TypeResolutionContext,
typeAliasExpansion: TypeAliasExpansion,
annotations: Annotations
): KotlinType {
val originalProjection = TypeProjectionImpl(Variance.INVARIANT, typeAliasExpansion.descriptor.underlyingType)
val expandedProjection = expandTypeProjectionForTypeAlias(c, originalProjection, typeAliasExpansion, null, 1)
if (expandedProjection.type.isError) return expandedProjection.type
assert(expandedProjection.projectionKind == Variance.INVARIANT) {
"Type alias expansion: result for ${typeAliasExpansion.descriptor} is ${expandedProjection.projectionKind}, should be invariant"
}
val abbreviatedType = KotlinTypeImpl.create(annotations, typeAliasExpansion.descriptor.typeConstructor,
originalProjection.type.isMarkedNullable,
typeAliasExpansion.arguments, MemberScope.Empty)
return expandedProjection.type.replace(
newAnnotations = annotations,
newCapabilities = withAbbreviatedType(abbreviatedType))
}
private fun expandTypeProjectionForTypeAlias(
c: TypeResolutionContext,
originalProjection: TypeProjection,
typeAliasExpansion: TypeAliasExpansion,
typeParameterDescriptor: TypeParameterDescriptor?,
recursionDepth: Int
): TypeProjection {
assertRecursionDepth(recursionDepth) {
"Too deep recursion while expanding type alias ${typeAliasExpansion.descriptor}"
}
val originalType = originalProjection.type
val typeAliasArgument = typeAliasExpansion.getReplacement(originalType.constructor)
if (typeAliasArgument == null) {
return substituteNonArgumentTypeForTypeAlias(c, originalProjection, typeAliasExpansion, recursionDepth)
}
val originalVariance =
if (originalProjection.projectionKind != Variance.INVARIANT)
originalProjection.projectionKind
else if (typeParameterDescriptor != null)
typeParameterDescriptor.variance
else
Variance.INVARIANT
val argumentVariance = typeAliasArgument.projectionKind
val substitutedVariance =
if (argumentVariance == Variance.INVARIANT)
originalVariance
else if (originalVariance == Variance.INVARIANT || originalVariance == argumentVariance)
argumentVariance
else if (typeAliasArgument.isStarProjection)
argumentVariance
else {
if (originalVariance != argumentVariance && !typeAliasArgument.isStarProjection) {
val argumentElement = typeParameterDescriptor?.let { typeAliasExpansion.context.argumentElements[it] }
if (argumentElement != null && typeParameterDescriptor != null) {
c.trace.report(CONFLICTING_PROJECTION.on(argumentElement, typeParameterDescriptor))
}
else {
c.trace.report(CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION.on(
typeAliasExpansion.context.element, typeAliasExpansion.descriptor.underlyingType))
}
}
argumentVariance
}
val substitutedType = TypeUtils.makeNullableIfNeeded(typeAliasArgument.type, originalType.isMarkedNullable)
return TypeProjectionImpl(substitutedVariance, substitutedType)
}
private fun substituteNonArgumentTypeForTypeAlias(
c: TypeResolutionContext,
originalProjection: TypeProjection,
typeAliasExpansion: TypeAliasExpansion,
recursionDepth: Int
): TypeProjection {
val type = originalProjection.type
val typeConstructor = type.constructor
val typeDescriptor = typeConstructor.declarationDescriptor
when (typeDescriptor) {
is TypeParameterDescriptor -> {
return originalProjection
}
is TypeAliasDescriptor -> {
if (typeAliasExpansion.isRecursion(typeDescriptor)) {
c.trace.report(RECURSIVE_TYPEALIAS_EXPANSION.on(typeAliasExpansion.context.element, typeDescriptor))
return TypeProjectionImpl(Variance.INVARIANT, ErrorUtils.createErrorType("Recursive type alias: ${typeDescriptor.name}"))
}
val expandedArguments = type.arguments.mapIndexed { i, typeAliasArgument ->
expandTypeProjectionForTypeAlias(c, typeAliasArgument, typeAliasExpansion, typeConstructor.parameters[i], recursionDepth)
}
val nestedExpansion = createNestedTypeAliasExpansion(typeAliasExpansion, typeDescriptor, expandedArguments)
val expandedType = expandTypeAlias(c, nestedExpansion, type.annotations)
return TypeProjectionImpl(originalProjection.projectionKind,
if (expandedType.isError) expandedType else expandedType.replace(newCapabilities = withAbbreviatedType(type)))
}
else -> {
val substitutedArguments = type.arguments.mapIndexed { i, originalArgument ->
expandTypeProjectionForTypeAlias(c, originalArgument, typeAliasExpansion, typeConstructor.parameters[i], recursionDepth + 1)
}
checkTypeArgumentsSubstitutionInTypeAliasExpansion(c, type, substitutedArguments, typeAliasExpansion)
val substitutedType = type.replace(newArguments = substitutedArguments)
return TypeProjectionImpl(originalProjection.projectionKind, substitutedType)
}
}
}
private fun checkTypeArgumentsSubstitutionInTypeAliasExpansion(
c: TypeResolutionContext,
type: KotlinType,
substitutedArguments: List<TypeProjection>,
typeAliasExpansion: TypeAliasExpansion
) {
val typeSubstitutor = TypeSubstitutor.create(type)
substitutedArguments.forEachIndexed { i, substitutedArgument ->
val typeParameter = type.constructor.parameters[i]
DescriptorResolver.checkBoundsInTypeAlias(typeAliasExpansion.context.element, substitutedArgument.type, typeParameter, typeSubstitutor, c.trace)
}
}
private fun createErrorTypeForTypeConstructor(
c: TypeResolutionContext,
arguments: List<KtTypeProjection>,
typeConstructor: TypeConstructor
) =
createErrorTypeAndResolveArguments(c, arguments, "[Error type: $typeConstructor]")
// Returns true in case when at least one argument for this class could be specified
// It could be always equal to 'typeConstructor.parameters.isNotEmpty()' unless local classes could captured type parameters
// from enclosing functions. In such cases you can not specify any argument:
@@ -583,6 +849,14 @@ class TypeResolver(
}
companion object {
private const val MAX_RECURSION_DEPTH = 100
private inline fun assertRecursionDepth(recursionDepth: Int, lazyMessage: () -> String) {
if (recursionDepth > MAX_RECURSION_DEPTH) {
throw AssertionError(lazyMessage())
}
}
@JvmStatic fun resolveProjectionKind(projectionKind: KtProjectionKind): Variance {
return when (projectionKind) {
KtProjectionKind.IN -> IN_VARIANCE
@@ -160,7 +160,7 @@ open class FileScopeProviderImpl(
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
if (name in excludedNames) return null
val classifier = scope.getContributedClassifier(name, location) ?: return null
val visible = Visibilities.isVisibleIgnoringReceiver(classifier as ClassDescriptor, fromDescriptor)
val visible = Visibilities.isVisibleIgnoringReceiver(classifier as DeclarationDescriptorWithVisibility, fromDescriptor)
return classifier.check { filteringKind == if (visible) FilteringKind.VISIBLE_CLASSES else FilteringKind.INVISIBLE_CLASSES }
}
@@ -224,6 +224,14 @@ public class LazyDeclarationResolver {
return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property);
}
@Override
public DeclarationDescriptor visitTypeAlias(@NotNull KtTypeAlias typeAlias, Void data) {
LookupLocation location = lookupLocationFor(typeAlias, typeAlias.isTopLevel());
MemberScope scopeForDeclaration = getMemberScopeDeclaredIn(typeAlias, location);
scopeForDeclaration.getContributedClassifier(typeAlias.getNameAsSafeName(), location);
return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, typeAlias);
}
@Override
public DeclarationDescriptor visitScript(@NotNull KtScript script, Void data) {
return getScriptDescriptor(script, lookupLocationFor(script, true));
@@ -36,29 +36,29 @@ abstract class AbstractPsiBasedDeclarationProvider(storageManager: StorageManage
val functions = ArrayListMultimap.create<Name, KtNamedFunction>()
val properties = ArrayListMultimap.create<Name, KtProperty>()
val classesAndObjects = ArrayListMultimap.create<Name, KtClassLikeInfo>() // order matters here
val typeAliases = ArrayListMultimap.create<Name, KtTypeAlias>()
fun putToIndex(declaration: KtDeclaration) {
if (declaration is KtAnonymousInitializer || declaration is KtSecondaryConstructor) return
allDeclarations.add(declaration)
if (declaration is KtNamedFunction) {
functions.put(safeNameForLazyResolve(declaration), declaration)
}
else if (declaration is KtProperty) {
properties.put(safeNameForLazyResolve(declaration), declaration)
}
else if (declaration is KtClassOrObject) {
classesAndObjects.put(safeNameForLazyResolve(declaration.getNameAsName()), KtClassInfoUtil.createClassLikeInfo(declaration))
}
else if (declaration is KtScript) {
val scriptInfo = KtScriptInfo(declaration)
classesAndObjects.put(scriptInfo.script.nameAsName, scriptInfo)
}
else if (declaration is KtParameter || declaration is KtDestructuringDeclaration) {
// Do nothing, just put it into allDeclarations is enough
}
else {
throw IllegalArgumentException("Unknown declaration: " + declaration)
when (declaration) {
is KtNamedFunction ->
functions.put(safeNameForLazyResolve(declaration), declaration)
is KtProperty ->
properties.put(safeNameForLazyResolve(declaration), declaration)
is KtTypeAlias ->
typeAliases.put(safeNameForLazyResolve(declaration.nameAsName), declaration)
is KtClassOrObject ->
classesAndObjects.put(safeNameForLazyResolve(declaration.nameAsName), KtClassInfoUtil.createClassLikeInfo(declaration))
is KtScript -> {
val scriptInfo = KtScriptInfo(declaration)
classesAndObjects.put(scriptInfo.script.nameAsName, scriptInfo)
}
is KtParameter, is KtDestructuringDeclaration -> {
// Do nothing, just put it into allDeclarations is enough
}
else -> throw IllegalArgumentException("Unknown declaration: " + declaration)
}
}
}
@@ -82,4 +82,7 @@ abstract class AbstractPsiBasedDeclarationProvider(storageManager: StorageManage
override fun getClassOrObjectDeclarations(name: Name): Collection<KtClassLikeInfo>
= index().classesAndObjects[ResolveSessionUtils.safeNameForLazyResolve(name)]
override fun getTypeAliasDeclarations(name: Name): Collection<KtTypeAlias>
= index().typeAliases[ResolveSessionUtils.safeNameForLazyResolve(name)]
}
@@ -32,4 +32,6 @@ class CombinedPackageMemberDeclarationProvider(val providers: Collection<Package
override fun getPropertyDeclarations(name: Name) = providers.flatMap { it.getPropertyDeclarations(name) }
override fun getClassOrObjectDeclarations(name: Name) = providers.flatMap { it.getClassOrObjectDeclarations(name) }
override fun getTypeAliasDeclarations(name: Name) = providers.flatMap { it.getTypeAliasDeclarations(name) }
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtTypeAlias
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
interface DeclarationProvider {
@@ -31,4 +32,6 @@ interface DeclarationProvider {
fun getPropertyDeclarations(name: Name): Collection<KtProperty>
fun getClassOrObjectDeclarations(name: Name): Collection<KtClassLikeInfo>
fun getTypeAliasDeclarations(name: Name): Collection<KtTypeAlias>
}
@@ -50,6 +50,7 @@ protected constructor(
private val classDescriptors: MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> = storageManager.createMemoizedFunction { resolveClassDescriptor(it) }
private val functionDescriptors: MemoizedFunctionToNotNull<Name, Collection<SimpleFunctionDescriptor>> = storageManager.createMemoizedFunction { doGetFunctions(it) }
private val propertyDescriptors: MemoizedFunctionToNotNull<Name, Collection<PropertyDescriptor>> = storageManager.createMemoizedFunction { doGetProperties(it) }
private val typeAliasDescriptors: MemoizedFunctionToNotNull<Name, Collection<TypeAliasDescriptor>> = storageManager.createMemoizedFunction { doGetTypeAliases(it) }
private fun resolveClassDescriptor(name: Name): List<ClassDescriptor> {
return declarationProvider.getClassOrObjectDeclarations(name).map {
@@ -60,9 +61,9 @@ protected constructor(
}.toReadOnlyList()
}
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassDescriptor? {
override fun getContributedClassifier(name: Name, location: LookupLocation): ClassifierDescriptor? {
recordLookup(name, location)
return classDescriptors(name).firstOrNull()
return classDescriptors(name).firstOrNull() ?: typeAliasDescriptors(name).firstOrNull()
}
override fun getContributedFunctions(name: Name, location: LookupLocation): Collection<SimpleFunctionDescriptor> {
@@ -120,6 +121,20 @@ protected constructor(
protected abstract fun getNonDeclaredProperties(name: Name, result: MutableSet<PropertyDescriptor>)
protected fun getContributedTypeAliasDescriptors(name: Name, location: LookupLocation): Collection<TypeAliasDescriptor> {
recordLookup(name, location)
return typeAliasDescriptors(name)
}
private fun doGetTypeAliases(name: Name): Collection<TypeAliasDescriptor> =
declarationProvider.getTypeAliasDeclarations(name).map { ktTypeAlias ->
c.descriptorResolver.resolveTypeAliasDescriptor(
thisDescriptor,
getScopeForMemberDeclarationResolution(ktTypeAlias),
ktTypeAlias,
trace)
}.toReadOnlyList()
protected fun computeDescriptorsFromDeclaredElements(
kindFilter: DescriptorKindFilter,
nameFilter: (Name) -> Boolean,
@@ -152,6 +167,12 @@ protected constructor(
result.addAll(getContributedVariables(name, location))
}
}
else if (declaration is KtTypeAlias) {
val name = declaration.nameAsSafeName
if (nameFilter(name)) {
result.addAll(getContributedTypeAliasDescriptors(name, location))
}
}
else if (declaration is KtScript) {
val name = declaration.nameAsSafeName
if (nameFilter(name)) {
@@ -161,9 +182,7 @@ protected constructor(
else if (declaration is KtDestructuringDeclaration) {
// MultiDeclarations are not supported on global level
}
else {
throw IllegalArgumentException("Unsupported declaration kind: " + declaration)
}
else throw IllegalArgumentException("Unsupported declaration kind: " + declaration)
}
return result.toReadOnlyList()
}
@@ -0,0 +1,111 @@
/*
* 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.
*/
package org.jetbrains.kotlin.resolve.lazy.descriptors
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorNonRootImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.storage.NotNullLazyValue
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeSubstitutor
class TypeAliasDescriptorImpl(
containingDeclaration: DeclarationDescriptor,
annotations: Annotations,
name: Name,
sourceElement: SourceElement,
private val fVisibility: Visibility
) : DeclarationDescriptorNonRootImpl(containingDeclaration, annotations, name, sourceElement),
TypeAliasDescriptor {
// TODO kotlinize some interfaces
private lateinit var fDeclaredTypeParameters: List<TypeParameterDescriptor>
private lateinit var lazyUnderlyingType: NotNullLazyValue<KotlinType>
override val underlyingType: KotlinType get() = lazyUnderlyingType()
fun initialize(declaredTypeParameters: List<TypeParameterDescriptor>, lazyUnderlyingType: NotNullLazyValue<KotlinType>) {
this.fDeclaredTypeParameters = declaredTypeParameters
this.lazyUnderlyingType = lazyUnderlyingType
}
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R =
visitor.visitTypeAliasDescriptor(this, data)
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> =
fDeclaredTypeParameters
override val underlyingClassDescriptor: ClassDescriptor
get() = underlyingType.constructor.declarationDescriptor as ClassDescriptor // TODO
override fun getModality() = Modality.FINAL
override fun getVisibility() = fVisibility
override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor =
if (substitutor.isEmpty) this
else TODO("typealias doSubstitute")
override fun getDefaultType(): KotlinType =
TODO("typealias getDefaultType")
override fun getTypeConstructor(): TypeConstructor =
typeConstructor
override fun toString(): String = "typealias ${name.asString()}"
private val typeConstructor = object : TypeConstructor {
override fun getDeclarationDescriptor(): TypeAliasDescriptor =
this@TypeAliasDescriptorImpl
override fun getParameters(): List<TypeParameterDescriptor> =
declarationDescriptor.declaredTypeParameters // TODO type parameters of outer class
override fun getSupertypes(): Collection<KotlinType> =
declarationDescriptor.underlyingType.constructor.supertypes
override fun isFinal(): Boolean =
declarationDescriptor.underlyingType.constructor.isFinal
override fun isDenotable(): Boolean =
true
override fun getBuiltIns(): KotlinBuiltIns =
declarationDescriptor.builtIns
override fun getAnnotations(): Annotations =
declarationDescriptor.annotations
}
companion object {
@JvmStatic fun create(
containingDeclaration: DeclarationDescriptor,
annotations: Annotations,
name: Name,
sourceElement: SourceElement,
visibility: Visibility
): TypeAliasDescriptorImpl =
TypeAliasDescriptorImpl(containingDeclaration, annotations, name, sourceElement, visibility)
}
}
@@ -73,6 +73,8 @@ enum class LexicalScopeKind(val withLocalDescriptors: Boolean) {
FUNCTION_HEADER(false),
FUNCTION_INNER_SCOPE(true),
TYPE_ALIAS_HEADER(false),
CODE_BLOCK(true),
LEFT_BOOLEAN_EXPRESSION(true),
+5
View File
@@ -0,0 +1,5 @@
typealias S = String
val OK: S = "OK"
fun box(): S = OK
@@ -0,0 +1,5 @@
typealias WithVariance<<!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>in<!> X, <!VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED!>out<!> Y> = Int
typealias WithBounds1<T : <!BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED!>T<!>> = Int
typealias WithBounds2<X : <!BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED!>Y<!>, Y : <!BOUND_ON_TYPE_ALIAS_PARAMETER_NOT_ALLOWED!>X<!>> = Int
val x: WithVariance<Int, Int> = 0
@@ -0,0 +1,6 @@
package
public val x: WithVariance<kotlin.Int, kotlin.Int> [= kotlin.Int] = 0
public typealias WithBounds1</*0*/ T : [ERROR : Cyclic upper bounds]> = kotlin.Int
public typealias WithBounds2</*0*/ X : [ERROR : Cyclic upper bounds], /*1*/ Y : [ERROR : Cyclic upper bounds]> = kotlin.Int
public typealias WithVariance</*0*/ in X, /*1*/ out Y> = kotlin.Int
@@ -0,0 +1,8 @@
class C<T>
typealias CA<T> = C<T>
val ca1: CA<Int> = C<Int>()
val ca2: CA<CA<Int>> = C<C<Int>>()
val ca3: CA<C<Int>> = C<C<Int>>()
val ca4: CA<Int?> = C<Int?>()
@@ -0,0 +1,14 @@
package
public val ca1: CA<kotlin.Int> [= C<kotlin.Int>]
public val ca2: CA<CA<kotlin.Int> [= C<kotlin.Int>]> [= C<CA<kotlin.Int> [= C<kotlin.Int>]>]
public val ca3: CA<C<kotlin.Int>> [= C<C<kotlin.Int>>]
public val ca4: CA<kotlin.Int?> [= C<kotlin.Int?>]
public final class C</*0*/ T> {
public constructor C</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public typealias CA</*0*/ T> = C<T>
@@ -0,0 +1,4 @@
typealias A = B
typealias B = A
val x: <!RECURSIVE_TYPEALIAS_EXPANSION!>A<!> = TODO()
@@ -0,0 +1,5 @@
package
public val x: [ERROR : Recursive type alias: A]
public typealias A = B
public typealias B = A
@@ -0,0 +1,8 @@
typealias S = String
typealias SS = S
typealias SSS = SS
val s1: SSS = ""
val s2: SSS? = null
val s3: List<SSS>? = null
val s4: List<List<SSS>?>? = null
@@ -0,0 +1,9 @@
package
public val s1: SSS [= kotlin.String] = ""
public val s2: SSS [= kotlin.String?] = null
public val s3: kotlin.collections.List<SSS [= kotlin.String]>? = null
public val s4: kotlin.collections.List<kotlin.collections.List<SSS [= kotlin.String]>?>? = null
public typealias S = kotlin.String
public typealias SS = S
public typealias SSS = SS
@@ -0,0 +1,20 @@
class In<in T>
class Out<out T>
class Inv<T>
typealias In1<T> = In<T>
typealias In2<T> = In<<!REDUNDANT_PROJECTION!>in<!> T>
typealias In3<T> = In<<!CONFLICTING_PROJECTION!>out<!> T>
typealias In4<T> = In<*>
typealias Out1<T> = Out<T>
typealias Out2<T> = Out<<!CONFLICTING_PROJECTION!>in<!> T>
typealias Out3<T> = Out<<!REDUNDANT_PROJECTION!>out<!> T>
typealias Out4<T> = Out<*>
typealias Inv1<T> = Inv<T>
typealias Inv2<T> = Inv<in T>
typealias Inv3<T> = Inv<out T>
typealias Inv4<T> = Inv<*>
val inv1: Inv1<Int> = Inv<Int>()
@@ -0,0 +1,36 @@
package
public val inv1: Inv1<kotlin.Int> [= Inv<kotlin.Int>]
public final class In</*0*/ in T> {
public constructor In</*0*/ in T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Inv</*0*/ T> {
public constructor Inv</*0*/ T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Out</*0*/ out T> {
public constructor Out</*0*/ out T>()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public typealias In1</*0*/ T> = In<T>
public typealias In2</*0*/ T> = In<in T>
public typealias In3</*0*/ T> = In<out T>
public typealias In4</*0*/ T> = In<*>
public typealias Inv1</*0*/ T> = Inv<T>
public typealias Inv2</*0*/ T> = Inv<in T>
public typealias Inv3</*0*/ T> = Inv<out T>
public typealias Inv4</*0*/ T> = Inv<*>
public typealias Out1</*0*/ T> = Out<T>
public typealias Out2</*0*/ T> = Out<in T>
public typealias Out3</*0*/ T> = Out<out T>
public typealias Out4</*0*/ T> = Out<*>
@@ -273,6 +273,14 @@ public class DescriptorValidator {
return true;
}
@Override
public Boolean visitTypeAliasDescriptor(
TypeAliasDescriptor descriptor, DiagnosticCollector data
) {
// TODO typealias
return true;
}
@Override
public Boolean visitModuleDeclaration(
ModuleDescriptor descriptor, DiagnosticCollector collector
@@ -436,6 +444,12 @@ public class DescriptorValidator {
return null;
}
@Override
public Void visitTypeAliasDescriptor(TypeAliasDescriptor descriptor, MemberScope data) {
// TODO typealias
return null;
}
@Override
public Void visitModuleDeclaration(
ModuleDescriptor descriptor, MemberScope scope
@@ -109,6 +109,12 @@ public class RecursiveDescriptorProcessor {
&& visitChildren(DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope()), data);
}
@Override
public Boolean visitTypeAliasDescriptor(TypeAliasDescriptor descriptor, D data) {
// TODO typealias
return true;
}
@Override
public Boolean visitModuleDeclaration(ModuleDescriptor descriptor, D data) {
return applyWorker(descriptor, data)
@@ -19012,6 +19012,45 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
}
}
@TestMetadata("compiler/testData/diagnostics/tests/typealias")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Typealias extends AbstractDiagnosticsTest {
public void testAllFilesPresentInTypealias() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/typealias"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("parameterRestrictions.kt")
public void testParameterRestrictions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/parameterRestrictions.kt");
doTest(fileName);
}
@TestMetadata("parameterSubstitution.kt")
public void testParameterSubstitution() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/parameterSubstitution.kt");
doTest(fileName);
}
@TestMetadata("recursive.kt")
public void testRecursive() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/recursive.kt");
doTest(fileName);
}
@TestMetadata("simpleTypeAlias.kt")
public void testSimpleTypeAlias() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/simpleTypeAlias.kt");
doTest(fileName);
}
@TestMetadata("substitutionVariance.kt")
public void testSubstitutionVariance() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/substitutionVariance.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/tests/unit")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -14321,6 +14321,21 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
}
@TestMetadata("compiler/testData/codegen/box/typealias")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Typealias extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInTypealias() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/typealias"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/typealias/simple.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/codegen/box/unaryOp")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -129,6 +129,12 @@ public class RecursiveDescriptorProcessorTest extends KotlinTestWithEnvironment
return true;
}
@Override
public Boolean visitTypeAliasDescriptor(TypeAliasDescriptor descriptor, Void data) {
add(descriptor); // TODO typealias
return null;
}
@Override
public Boolean visitModuleDeclaration(ModuleDescriptor descriptor, Void data) {
add(descriptor);
@@ -28,7 +28,7 @@ import org.jetbrains.kotlin.types.TypeSubstitutor;
import java.util.Collection;
import java.util.List;
public interface ClassDescriptor extends ClassifierDescriptor, MemberDescriptor, ClassOrPackageFragmentDescriptor {
public interface ClassDescriptor extends ClassifierDescriptorWithTypeParameters, MemberDescriptor, ClassOrPackageFragmentDescriptor {
@NotNull
MemberScope getMemberScope(@NotNull List<? extends TypeProjection> typeArguments);
@@ -100,6 +100,7 @@ public interface ClassDescriptor extends ClassifierDescriptor, MemberDescriptor,
* captured parameters from outer declaration.
* @return list of type parameters actually declared type parameters in current class
*/
@Override
@ReadOnly
@NotNull
List<TypeParameterDescriptor> getDeclaredTypeParameters();
@@ -0,0 +1,28 @@
/*
* 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.
*/
package org.jetbrains.kotlin.descriptors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.ReadOnly;
import java.util.List;
public interface ClassifierDescriptorWithTypeParameters extends ClassifierDescriptor {
@ReadOnly
@NotNull
List<TypeParameterDescriptor> getDeclaredTypeParameters();
}
@@ -29,6 +29,8 @@ public interface DeclarationDescriptorVisitor<R, D> {
R visitClassDescriptor(ClassDescriptor descriptor, D data);
R visitTypeAliasDescriptor(TypeAliasDescriptor descriptor, D data);
R visitModuleDeclaration(ModuleDescriptor descriptor, D data);
R visitConstructorDescriptor(ConstructorDescriptor constructorDescriptor, D data);
@@ -0,0 +1,28 @@
/*
* 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.
*/
package org.jetbrains.kotlin.descriptors
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
interface TypeAliasDescriptor : ClassifierDescriptorWithTypeParameters, MemberDescriptor {
val underlyingType: KotlinType
val underlyingClassDescriptor: ClassDescriptor
override fun substitute(substitutor: TypeSubstitutor): TypeAliasDescriptor
}
@@ -53,6 +53,11 @@ public class DeclarationDescriptorVisitorEmptyBodies<R, D> implements Declaratio
return visitDeclarationDescriptor(descriptor, data);
}
@Override
public R visitTypeAliasDescriptor(TypeAliasDescriptor descriptor, D data) {
return visitDeclarationDescriptor(descriptor, data);
}
@Override
public R visitModuleDeclaration(ModuleDescriptor descriptor, D data) {
return visitDeclarationDescriptor(descriptor, data);
@@ -128,6 +128,19 @@ internal class DescriptorRendererImpl(
}
private fun renderNormalizedType(type: KotlinType): String {
val abbreviated = type.getCapability(AbbreviatedType::class.java)?.abbreviatedType
if (abbreviated != null) {
// TODO nullability is lost for abbreviated type?
val abbreviatedRendered = renderNormalizedTypeAsIs(abbreviated)
val unabbreviatedRendered = renderNormalizedTypeAsIs(type)
return "$abbreviatedRendered [= $unabbreviatedRendered]"
}
return renderNormalizedTypeAsIs(type)
}
private fun renderNormalizedTypeAsIs(type: KotlinType): String {
if (type is LazyType && debugMode) {
return type.toString()
}
@@ -271,7 +284,7 @@ internal class DescriptorRendererImpl(
override fun renderTypeConstructor(typeConstructor: TypeConstructor): String {
val cd = typeConstructor.declarationDescriptor
return when (cd) {
is TypeParameterDescriptor, is ClassDescriptor -> renderClassifierName(cd)
is TypeParameterDescriptor, is ClassDescriptor, is TypeAliasDescriptor -> renderClassifierName(cd)
null -> typeConstructor.toString()
else -> error("Unexpected classifier: " + cd.javaClass)
}
@@ -791,6 +804,15 @@ internal class DescriptorRendererImpl(
}
}
private fun renderTypeAlias(typeAlias: TypeAliasDescriptor, builder: StringBuilder) {
renderAnnotations(typeAlias, builder)
renderVisibility(typeAlias.visibility, builder)
builder.append(renderKeyword("typealias")).append(" ")
renderName(typeAlias, builder)
renderTypeParameters(typeAlias.declaredTypeParameters, builder, true)
builder.append(" = ").append(renderType(typeAlias.underlyingType))
}
/* CLASSES */
private fun renderClass(klass: ClassDescriptor, builder: StringBuilder) {
val isEnumEntry = klass.kind == ClassKind.ENUM_ENTRY
@@ -961,6 +983,10 @@ internal class DescriptorRendererImpl(
override fun visitClassDescriptor(descriptor: ClassDescriptor, builder: StringBuilder) {
renderClass(descriptor, builder)
}
override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, builder: StringBuilder) {
renderTypeAlias(descriptor, builder)
}
}
private fun renderSpaceIfNeeded(builder: StringBuilder) {
@@ -84,3 +84,13 @@ fun sameTypeConstructors(first: KotlinType, second: KotlinType): Boolean {
return first.getCapability(typeRangeCapability)?.sameTypeConstructor(second) ?: false
|| second.getCapability(typeRangeCapability)?.sameTypeConstructor(first) ?: false
}
interface AbbreviatedType : TypeCapability {
val abbreviatedType : KotlinType
}
fun KotlinType.hasAbbreviatedType(): Boolean =
getCapability(AbbreviatedType::class.java) != null
fun KotlinType.getAbbreviatedType(): KotlinType? =
getCapability(AbbreviatedType::class.java)?.abbreviatedType
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
@@ -228,11 +229,11 @@ public class TypeUtils {
}
@NotNull
public static KotlinType makeUnsubstitutedType(ClassDescriptor classDescriptor, MemberScope unsubstitutedMemberScope) {
if (ErrorUtils.isError(classDescriptor)) {
return ErrorUtils.createErrorType("Unsubstituted type for " + classDescriptor);
public static KotlinType makeUnsubstitutedType(ClassifierDescriptor classifierDescriptor, MemberScope unsubstitutedMemberScope) {
if (ErrorUtils.isError(classifierDescriptor)) {
return ErrorUtils.createErrorType("Unsubstituted type for " + classifierDescriptor);
}
TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
List<TypeProjection> arguments = getDefaultTypeProjections(typeConstructor.getParameters());
return KotlinTypeImpl.create(
Annotations.Companion.getEMPTY(),
@@ -561,6 +561,8 @@ class ResolveElementCache(
override fun getFunctions(): MutableMap<KtNamedFunction, SimpleFunctionDescriptor> = hashMapOf()
override fun getTypeAliases(): MutableMap<KtTypeAlias, TypeAliasDescriptor> = hashMapOf()
override fun getDeclaringScope(declaration: KtDeclaration): LexicalScope? = declaringScopes(declaration)
override fun getScripts(): MutableMap<KtScript, LazyScriptDescriptor> = hashMapOf()
@@ -105,7 +105,7 @@ class QuickFixRegistrar : QuickFixContributor {
REDUNDANT_PROJECTION.registerFactory(RemoveModifierFix.createRemoveProjectionFactory(true))
INCOMPATIBLE_MODIFIERS.registerFactory(RemoveModifierFix.createRemoveModifierFactory(false))
VARIANCE_ON_TYPE_PARAMETER_OF_FUNCTION_OR_PROPERTY.registerFactory(RemoveModifierFix.createRemoveVarianceFactory())
VARIANCE_ON_TYPE_PARAMETER_NOT_ALLOWED.registerFactory(RemoveModifierFix.createRemoveVarianceFactory())
val removeOpenModifierFactory = RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OPEN_KEYWORD)
NON_FINAL_MEMBER_IN_FINAL_CLASS.registerFactory(AddModifierFix.createFactory(OPEN_KEYWORD, KtClass::class.java),