/*
* 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.impl;
import kotlin.jvm.functions.
Function0;
import org.jetbrains.annotations.
NotNull;
import org.jetbrains.kotlin.descriptors.
ClassDescriptor;
import org.jetbrains.kotlin.descriptors.
DeclarationDescriptorVisitor;
import org.jetbrains.kotlin.descriptors.
ReceiverParameterDescriptor;
import org.jetbrains.kotlin.name.
Name;
import org.jetbrains.kotlin.resolve.scopes.
InnerClassesScopeWrapper;
import org.jetbrains.kotlin.resolve.scopes.
MemberScope;
import org.jetbrains.kotlin.resolve.scopes.
SubstitutingScope;
import org.jetbrains.kotlin.storage.
NotNullLazyValue;
import org.jetbrains.kotlin.storage.
StorageManager;
import org.jetbrains.kotlin.types.*;
import java.util.
List;
public abstract class
AbstractClassDescriptor implements
ClassDescriptor {
private final
Name name;
protected final
NotNullLazyValue<
SimpleType>
defaultType;
private final
NotNullLazyValue<
MemberScope>
unsubstitutedInnerClassesScope;
private final
NotNullLazyValue<
ReceiverParameterDescriptor>
thisAsReceiverParameter;
public
AbstractClassDescriptor(@
NotNull StorageManager storageManager, @
NotNull Name name) {
this.
name =
name;
this.
defaultType =
storageManager.
createLazyValue(new
Function0<
SimpleType>() {
@
Override
public
SimpleType invoke() {
return
TypeUtils.
makeUnsubstitutedType(
AbstractClassDescriptor.this,
getUnsubstitutedMemberScope());
}
});
this.
unsubstitutedInnerClassesScope =
storageManager.
createLazyValue(new
Function0<
MemberScope>() {
@
Override
public
MemberScope invoke() {
return new
InnerClassesScopeWrapper(
getUnsubstitutedMemberScope());
}
});
this.
thisAsReceiverParameter =
storageManager.
createLazyValue(new
Function0<
ReceiverParameterDescriptor>() {
@
Override
public
ReceiverParameterDescriptor invoke() {
return new
LazyClassReceiverParameterDescriptor(
AbstractClassDescriptor.this);
}
});
}
@
NotNull
@
Override
public
Name getName() {
return
name;
}
@
NotNull
@
Override
public
ClassDescriptor getOriginal() {
return this;
}
@
NotNull
@
Override
public
MemberScope getUnsubstitutedInnerClassesScope() {
return
unsubstitutedInnerClassesScope.
invoke();
}
@
NotNull
@
Override
public
ReceiverParameterDescriptor getThisAsReceiverParameter() {
return
thisAsReceiverParameter.
invoke();
}
@
NotNull
@
Override
public
MemberScope getMemberScope(@
NotNull List<? extends
TypeProjection>
typeArguments) {
assert
typeArguments.
size() ==
getTypeConstructor().
getParameters().
size() : "Illegal number of type arguments: expected "
+
getTypeConstructor().
getParameters().
size() + " but was " +
typeArguments.
size()
+ " for " +
getTypeConstructor() + " " +
getTypeConstructor().
getParameters();
if (
typeArguments.
isEmpty()) return
getUnsubstitutedMemberScope();
TypeSubstitutor substitutor =
TypeConstructorSubstitution.
create(
getTypeConstructor(),
typeArguments).
buildSubstitutor();
return new
SubstitutingScope(
getUnsubstitutedMemberScope(),
substitutor);
}
@
NotNull
@
Override
public
MemberScope getMemberScope(@
NotNull TypeSubstitution typeSubstitution) {
if (
typeSubstitution.
isEmpty()) return
getUnsubstitutedMemberScope();
TypeSubstitutor substitutor =
TypeSubstitutor.
create(
typeSubstitution);
return new
SubstitutingScope(
getUnsubstitutedMemberScope(),
substitutor);
}
@
NotNull
@
Override
public
ClassDescriptor substitute(@
NotNull TypeSubstitutor substitutor) {
if (
substitutor.
isEmpty()) {
return this;
}
return new
LazySubstitutingClassDescriptor(this,
substitutor);
}
@
NotNull
@
Override
public
SimpleType getDefaultType() {
return
defaultType.
invoke();
}
@
Override
public void
acceptVoid(
DeclarationDescriptorVisitor<
Void,
Void>
visitor) {
visitor.
visitClassDescriptor(this, null);
}
@
Override
public <R, D> R
accept(
DeclarationDescriptorVisitor<R, D>
visitor, D
data) {
return
visitor.
visitClassDescriptor(this,
data);
}
}