001/* 002 * Copyright 2010-2013 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.jetbrains.jet.lang.descriptors.impl; 018 019import org.jetbrains.annotations.NotNull; 020import org.jetbrains.jet.lang.descriptors.ClassDescriptor; 021import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor; 022import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; 023import org.jetbrains.jet.lang.resolve.scopes.JetScope; 024import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope; 025import org.jetbrains.jet.lang.types.*; 026 027import java.util.List; 028import java.util.Map; 029 030public abstract class ClassDescriptorBase implements ClassDescriptor { 031 032 protected JetType defaultType; 033 034 protected abstract JetScope getScopeForMemberLookup(); 035 036 @NotNull 037 @Override 038 public JetScope getMemberScope(List<TypeProjection> typeArguments) { 039 assert typeArguments.size() == getTypeConstructor().getParameters().size() : "Illegal number of type arguments: expected " 040 + getTypeConstructor().getParameters().size() + " but was " + typeArguments.size() 041 + " for " + getTypeConstructor() + " " + getTypeConstructor().getParameters(); 042 if (typeArguments.isEmpty()) return getScopeForMemberLookup(); 043 044 List<TypeParameterDescriptor> typeParameters = getTypeConstructor().getParameters(); 045 Map<TypeConstructor, TypeProjection> substitutionContext = SubstitutionUtils.buildSubstitutionContext(typeParameters, typeArguments); 046 047 // Unsafe substitutor is OK, because no recursion can hurt us upon a trivial substitution: 048 // all the types are written explicitly in the code already, they can not get infinite. 049 // One exception is *-projections, but they need to be handled separately anyways. 050 TypeSubstitutor substitutor = TypeSubstitutor.createUnsafe(substitutionContext); 051 return new SubstitutingScope(getScopeForMemberLookup(), substitutor); 052 } 053 054 @NotNull 055 @Override 056 public ClassDescriptor substitute(@NotNull TypeSubstitutor substitutor) { 057 if (substitutor.isEmpty()) { 058 return this; 059 } 060 return new LazySubstitutingClassDescriptor(this, substitutor); 061 } 062 063 @NotNull 064 @Override 065 public JetType getDefaultType() { 066 if (defaultType == null) { 067 defaultType = TypeUtils.makeUnsubstitutedType(this, getScopeForMemberLookup()); 068 } 069 return defaultType; 070 } 071 072 @Override 073 public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) { 074 visitor.visitClassDescriptor(this, null); 075 } 076 077 @Override 078 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) { 079 return visitor.visitClassDescriptor(this, data); 080 } 081}