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