001    /*
002     * Copyright 2010-2015 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.ArraysKt;
032    import kotlin.jvm.functions.Function1;
033    import org.jetbrains.annotations.NotNull;
034    import org.jetbrains.annotations.Nullable;
035    import org.jetbrains.kotlin.idea.KotlinLanguage;
036    import org.jetbrains.kotlin.psi.*;
037    
038    import java.util.List;
039    
040    public abstract class KtWrappingLightClass extends AbstractLightClass implements KtLightClass, PsiExtensibleClass {
041        private final ClassInnerStuffCache myInnersCache = new ClassInnerStuffCache(this);
042    
043        protected KtWrappingLightClass(PsiManager manager) {
044            super(manager, KotlinLanguage.INSTANCE);
045        }
046    
047        @Nullable
048        @Override
049        public abstract KtClassOrObject getOrigin();
050    
051        @NotNull
052        @Override
053        public abstract PsiClass getDelegate();
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                    KtDeclaration declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(field);
123                    return KtLightFieldImpl.Factory.create(declaration, 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                    KtDeclaration declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(method);
135                    if (declaration instanceof KtPropertyAccessor) {
136                        declaration = PsiTreeUtil.getParentOfType(declaration, KtProperty.class);
137                    }
138    
139                    return KtLightMethodImpl.Factory.create(method, declaration, KtWrappingLightClass.this);
140                }
141            });
142        }
143    
144        @Override
145        public boolean processDeclarations(
146                @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place
147        ) {
148            if (isEnum()) {
149                if (!PsiClassImplUtil.processDeclarationsInEnum(processor, state, myInnersCache)) return false;
150            }
151    
152            return super.processDeclarations(processor, state, lastParent, place);
153        }
154    
155        @Override
156        public String getText() {
157            KtClassOrObject origin = getOrigin();
158            return origin == null ? "" : origin.getText();
159        }
160    
161        @NotNull
162        @Override
163        public Language getLanguage() {
164            return KotlinLanguage.INSTANCE;
165        }
166    
167        @Override
168        public ItemPresentation getPresentation() {
169            return ItemPresentationProviders.getItemPresentation(this);
170        }
171    
172        @Override
173        public abstract boolean equals(Object obj);
174    
175        @Override
176        public abstract int hashCode();
177    
178        @Override
179        public PsiElement getContext() {
180            return getParent();
181        }
182    }