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