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