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