001    /*
002     * Copyright 2010-2014 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.jet.asJava;
018    
019    import com.intellij.lang.Language;
020    import com.intellij.psi.*;
021    import com.intellij.psi.impl.PsiClassImplUtil;
022    import com.intellij.psi.impl.light.AbstractLightClass;
023    import com.intellij.psi.impl.light.LightField;
024    import com.intellij.psi.impl.light.LightMethod;
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.util.Function;
029    import com.intellij.util.containers.ContainerUtil;
030    import org.jetbrains.annotations.NotNull;
031    import org.jetbrains.jet.lang.psi.*;
032    
033    import java.util.List;
034    
035    public abstract class KotlinWrappingLightClass extends AbstractLightClass implements KotlinLightClass, PsiExtensibleClass {
036        private final ClassInnerStuffCache myInnersCache = new ClassInnerStuffCache(this);
037    
038        protected KotlinWrappingLightClass(PsiManager manager, Language language) {
039            super(manager, language);
040        }
041    
042        @NotNull
043        @Override
044        public abstract PsiClass getDelegate();
045    
046        @Override
047        @NotNull
048        public PsiField[] getFields() {
049            return myInnersCache.getFields();
050        }
051    
052        @Override
053        @NotNull
054        public PsiMethod[] getMethods() {
055            return myInnersCache.getMethods();
056        }
057    
058        @Override
059        @NotNull
060        public PsiMethod[] getConstructors() {
061            return myInnersCache.getConstructors();
062        }
063    
064        @Override
065        @NotNull
066        public PsiClass[] getInnerClasses() {
067            return myInnersCache.getInnerClasses();
068        }
069    
070        @Override
071        @NotNull
072        public PsiField[] getAllFields() {
073            return PsiClassImplUtil.getAllFields(this);
074        }
075    
076        @Override
077        @NotNull
078        public PsiMethod[] getAllMethods() {
079            return PsiClassImplUtil.getAllMethods(this);
080        }
081    
082        @Override
083        @NotNull
084        public PsiClass[] getAllInnerClasses() {
085            return PsiClassImplUtil.getAllInnerClasses(this);
086        }
087    
088        @Override
089        public PsiField findFieldByName(String name, boolean checkBases) {
090            return myInnersCache.findFieldByName(name, checkBases);
091        }
092    
093        @Override
094        @NotNull
095        public PsiMethod[] findMethodsByName(String name, boolean checkBases) {
096            return myInnersCache.findMethodsByName(name, checkBases);
097        }
098    
099        @Override
100        public PsiClass findInnerClassByName(String name, boolean checkBases) {
101            return myInnersCache.findInnerClassByName(name, checkBases);
102        }
103    
104        @NotNull
105        @Override
106        public List<PsiField> getOwnFields() {
107            return ContainerUtil.map(getDelegate().getFields(), new Function<PsiField, PsiField>() {
108                @Override
109                public PsiField fun(PsiField field) {
110                    JetDeclaration declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(field);
111                    if (declaration instanceof JetEnumEntry) {
112                        assert field instanceof PsiEnumConstant : "Field delegate should be an enum constant (" + field.getName() + "):\n" +
113                                                                  JetPsiUtil.getElementTextWithContext(declaration);
114                        return new KotlinLightEnumConstant(myManager, (JetEnumEntry) declaration, ((PsiEnumConstant) field),
115                                                           KotlinWrappingLightClass.this);
116                    }
117                    if (declaration instanceof JetProperty) {
118                        return new KotlinLightFieldForDeclaration(myManager, (JetProperty) declaration, field, KotlinWrappingLightClass.this);
119                    }
120                    return new LightField(myManager, field, KotlinWrappingLightClass.this);
121                }
122            });
123        }
124    
125        @NotNull
126        @Override
127        public List<PsiMethod> getOwnMethods() {
128            return ContainerUtil.map(getDelegate().getMethods(), new Function<PsiMethod, PsiMethod>() {
129                @Override
130                public PsiMethod fun(PsiMethod method) {
131                    JetDeclaration declaration = ClsWrapperStubPsiFactory.getOriginalDeclaration(method);
132                    return declaration != null
133                           ? new KotlinLightMethodForDeclaration(myManager, method, declaration, KotlinWrappingLightClass.this)
134                           : new LightMethod(myManager, method, KotlinWrappingLightClass.this);
135                }
136            });
137        }
138    
139        @Override
140        public boolean processDeclarations(
141                @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place
142        ) {
143            if (isEnum()) {
144                if (!PsiClassImplUtil.processDeclarationsInEnum(processor, state, myInnersCache)) return false;
145            }
146    
147            return super.processDeclarations(processor, state, lastParent, place);
148        }
149    
150        @Override
151        public String getText() {
152            JetClassOrObject origin = getOrigin();
153            return origin == null ? null : origin.getText();
154        }
155    }