001    /*
002     * Copyright 2010-2016 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    
017    package org.jetbrains.kotlin.asJava.classes;
018    
019    import com.intellij.lang.Language;
020    import com.intellij.navigation.ItemPresentation;
021    import com.intellij.navigation.ItemPresentationProviders;
022    import com.intellij.psi.*;
023    import com.intellij.psi.impl.PsiClassImplUtil;
024    import com.intellij.psi.impl.light.AbstractLightClass;
025    import com.intellij.psi.impl.source.ClassInnerStuffCache;
026    import com.intellij.psi.impl.source.PsiExtensibleClass;
027    import com.intellij.psi.scope.PsiScopeProcessor;
028    import com.intellij.psi.util.PsiTreeUtil;
029    import com.intellij.util.Function;
030    import com.intellij.util.containers.ContainerUtil;
031    import kotlin.collections.ArraysKt;
032    import kotlin.jvm.functions.Function1;
033    import org.jetbrains.annotations.NotNull;
034    import org.jetbrains.kotlin.asJava.builder.ClsWrapperStubPsiFactory;
035    import org.jetbrains.kotlin.asJava.builder.LightMemberOrigin;
036    import org.jetbrains.kotlin.asJava.builder.LightMemberOriginForDeclaration;
037    import org.jetbrains.kotlin.asJava.elements.KtLightFieldImpl;
038    import org.jetbrains.kotlin.asJava.elements.KtLightMethodImpl;
039    import org.jetbrains.kotlin.idea.KotlinLanguage;
040    import org.jetbrains.kotlin.psi.KtClassOrObject;
041    import org.jetbrains.kotlin.psi.KtDeclaration;
042    import org.jetbrains.kotlin.psi.KtProperty;
043    import org.jetbrains.kotlin.psi.KtPropertyAccessor;
044    
045    import java.util.List;
046    
047    public abstract class KtLightClassBase extends AbstractLightClass implements KtLightClass, PsiExtensibleClass {
048        private final ClassInnerStuffCache myInnersCache = new ClassInnerStuffCache(this);
049    
050        protected KtLightClassBase(PsiManager manager) {
051            super(manager, KotlinLanguage.INSTANCE);
052        }
053    
054        @NotNull
055        @Override
056        public PsiClass getDelegate() {
057            return getClsDelegate();
058        }
059    
060        @Override
061        @NotNull
062        public PsiField[] getFields() {
063            return myInnersCache.getFields();
064        }
065    
066        @Override
067        @NotNull
068        public PsiMethod[] getMethods() {
069            return myInnersCache.getMethods();
070        }
071    
072        @Override
073        @NotNull
074        public PsiMethod[] getConstructors() {
075            return myInnersCache.getConstructors();
076        }
077    
078        @Override
079        @NotNull
080        public PsiClass[] getInnerClasses() {
081            return myInnersCache.getInnerClasses();
082        }
083    
084        @Override
085        @NotNull
086        public PsiField[] getAllFields() {
087            return PsiClassImplUtil.getAllFields(this);
088        }
089    
090        @Override
091        @NotNull
092        public PsiMethod[] getAllMethods() {
093            return PsiClassImplUtil.getAllMethods(this);
094        }
095    
096        @Override
097        @NotNull
098        public PsiClass[] getAllInnerClasses() {
099            return PsiClassImplUtil.getAllInnerClasses(this);
100        }
101    
102        @Override
103        public PsiField findFieldByName(String name, boolean checkBases) {
104            return myInnersCache.findFieldByName(name, checkBases);
105        }
106    
107        @Override
108        @NotNull
109        public PsiMethod[] findMethodsByName(String name, boolean checkBases) {
110            return myInnersCache.findMethodsByName(name, checkBases);
111        }
112    
113        @Override
114        public PsiClass findInnerClassByName(String name, boolean checkBases) {
115            return myInnersCache.findInnerClassByName(name, checkBases);
116        }
117    
118        /**
119         * @see org.jetbrains.kotlin.codegen.binding.CodegenBinding#ENUM_ENTRY_CLASS_NEED_SUBCLASS
120          */
121        @NotNull
122        @Override
123        public List<PsiField> getOwnFields() {
124            return ContainerUtil.map(getDelegate().getFields(), new Function<PsiField, PsiField>() {
125                @Override
126                public PsiField fun(PsiField field) {
127                    LightMemberOrigin origin = ClsWrapperStubPsiFactory.getMemberOrigin(field);
128                    return KtLightFieldImpl.Factory.create(origin, field, KtLightClassBase.this);
129                }
130            });
131        }
132    
133        @NotNull
134        @Override
135        public List<PsiMethod> getOwnMethods() {
136            return ArraysKt.map(getDelegate().getMethods(), new Function1<PsiMethod, PsiMethod>() {
137                @Override
138                public PsiMethod invoke(PsiMethod method) {
139                    LightMemberOriginForDeclaration origin = ClsWrapperStubPsiFactory.getMemberOrigin(method);
140                    KtDeclaration originalElement = origin != null ? origin.getOriginalElement() : null;
141                    if (originalElement instanceof KtPropertyAccessor) {
142                        //noinspection ConstantConditions
143                        origin = origin.copy(PsiTreeUtil.getParentOfType(originalElement, KtProperty.class), origin.getOriginKind());
144                    }
145    
146                    return KtLightMethodImpl.Factory.create(method, origin, KtLightClassBase.this);
147                }
148            });
149        }
150    
151        @Override
152        public boolean processDeclarations(
153                @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place
154        ) {
155            if (isEnum()) {
156                if (!PsiClassImplUtil.processDeclarationsInEnum(processor, state, myInnersCache)) return false;
157            }
158    
159            return super.processDeclarations(processor, state, lastParent, place);
160        }
161    
162        @Override
163        public String getText() {
164            KtClassOrObject origin = getKotlinOrigin();
165            return origin == null ? "" : origin.getText();
166        }
167    
168        @NotNull
169        @Override
170        public Language getLanguage() {
171            return KotlinLanguage.INSTANCE;
172        }
173    
174        @Override
175        public ItemPresentation getPresentation() {
176            return ItemPresentationProviders.getItemPresentation(this);
177        }
178    
179        @Override
180        public abstract boolean equals(Object obj);
181    
182        @Override
183        public abstract int hashCode();
184    
185        @Override
186        public PsiElement getContext() {
187            return getParent();
188        }
189    }