001/* 002 * Copyright 2010-2013 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 017package org.jetbrains.jet.lang.resolve.lazy.descriptors; 018 019import com.google.common.collect.Sets; 020import com.intellij.openapi.util.Computable; 021import com.intellij.util.Function; 022import com.intellij.util.containers.ContainerUtil; 023import org.jetbrains.annotations.NotNull; 024import org.jetbrains.annotations.Nullable; 025import org.jetbrains.jet.lang.descriptors.*; 026import org.jetbrains.jet.lang.psi.*; 027import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; 028import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil; 029import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProvider; 030import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNotNull; 031import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue; 032import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager; 033import org.jetbrains.jet.lang.resolve.name.LabelName; 034import org.jetbrains.jet.lang.resolve.name.Name; 035import org.jetbrains.jet.lang.resolve.scopes.JetScope; 036 037import java.util.Collection; 038import java.util.Collections; 039import java.util.List; 040import java.util.Set; 041 042import static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve; 043import static org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager.ReferenceKind.STRONG; 044 045public abstract class AbstractLazyMemberScope<D extends DeclarationDescriptor, DP extends DeclarationProvider> implements JetScope { 046 protected final ResolveSession resolveSession; 047 protected final DP declarationProvider; 048 protected final D thisDescriptor; 049 050 private final MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> classDescriptors; 051 private final MemoizedFunctionToNotNull<Name, List<ClassDescriptor>> objectDescriptors; 052 053 private final MemoizedFunctionToNotNull<Name, Set<FunctionDescriptor>> functionDescriptors; 054 private final MemoizedFunctionToNotNull<Name, Set<VariableDescriptor>> propertyDescriptors; 055 056 private static class AllDescriptors { 057 private final Collection<DeclarationDescriptor> all = Sets.newLinkedHashSet(); 058 private final Collection<ClassDescriptor> objects = Sets.newLinkedHashSet(); 059 } 060 061 private final NotNullLazyValue<AllDescriptors> allDescriptors; 062 063 protected AbstractLazyMemberScope( 064 @NotNull ResolveSession resolveSession, 065 @NotNull DP declarationProvider, 066 @NotNull D thisDescriptor 067 ) { 068 this.resolveSession = resolveSession; 069 this.declarationProvider = declarationProvider; 070 this.thisDescriptor = thisDescriptor; 071 072 StorageManager storageManager = resolveSession.getStorageManager(); 073 this.classDescriptors = storageManager.createMemoizedFunction(new Function<Name, List<ClassDescriptor>>() { 074 @Override 075 public List<ClassDescriptor> fun(Name name) { 076 return resolveClassOrObjectDescriptor(name, false); 077 } 078 }, STRONG); 079 this.objectDescriptors = storageManager.createMemoizedFunction(new Function<Name, List<ClassDescriptor>>() { 080 @Override 081 public List<ClassDescriptor> fun(Name name) { 082 return resolveClassOrObjectDescriptor(name, true); 083 } 084 }, STRONG); 085 086 this.functionDescriptors = storageManager.createMemoizedFunction(new Function<Name, Set<FunctionDescriptor>>() { 087 @Override 088 public Set<FunctionDescriptor> fun(Name name) { 089 return doGetFunctions(name); 090 } 091 }, STRONG); 092 this.propertyDescriptors = storageManager.createMemoizedFunction(new Function<Name, Set<VariableDescriptor>>() { 093 @Override 094 public Set<VariableDescriptor> fun(Name name) { 095 return doGetProperties(name); 096 } 097 }, STRONG); 098 099 this.allDescriptors = storageManager.createLazyValue(new Computable<AllDescriptors>() { 100 @Override 101 public AllDescriptors compute() { 102 return computeAllDescriptors(); 103 } 104 }); 105 } 106 107 @Nullable 108 private List<ClassDescriptor> resolveClassOrObjectDescriptor(@NotNull final Name name, final boolean object) { 109 Collection<JetClassOrObject> classOrObjectDeclarations = declarationProvider.getClassOrObjectDeclarations(name); 110 111 return ContainerUtil.mapNotNull(classOrObjectDeclarations, new Function<JetClassOrObject, ClassDescriptor>() { 112 @Override 113 public ClassDescriptor fun(JetClassOrObject classOrObject) { 114 if (object != declaresObjectOrEnumConstant(classOrObject)) return null; 115 116 return new LazyClassDescriptor(resolveSession, thisDescriptor, name, 117 JetClassInfoUtil.createClassLikeInfo(classOrObject)); 118 } 119 }); 120 } 121 122 private static boolean declaresObjectOrEnumConstant(JetClassOrObject declaration) { 123 return declaration instanceof JetObjectDeclaration || declaration instanceof JetEnumEntry; 124 } 125 126 @Override 127 public ClassifierDescriptor getClassifier(@NotNull Name name) { 128 return first(classDescriptors.fun(name)); 129 } 130 131 @Override 132 public ClassDescriptor getObjectDescriptor(@NotNull Name name) { 133 return first(objectDescriptors.fun(name)); 134 } 135 136 private static <T> T first(@NotNull List<T> list) { 137 if (list.isEmpty()) return null; 138 return list.get(0); 139 } 140 141 @NotNull 142 @Override 143 public Set<FunctionDescriptor> getFunctions(@NotNull Name name) { 144 return functionDescriptors.fun(name); 145 } 146 147 @NotNull 148 private Set<FunctionDescriptor> doGetFunctions(@NotNull Name name) { 149 Set<FunctionDescriptor> result = Sets.newLinkedHashSet(); 150 151 Collection<JetNamedFunction> declarations = declarationProvider.getFunctionDeclarations(name); 152 for (JetNamedFunction functionDeclaration : declarations) { 153 JetScope resolutionScope = getScopeForMemberDeclarationResolution(functionDeclaration); 154 result.add(resolveSession.getInjector().getDescriptorResolver().resolveFunctionDescriptorWithAnnotationArguments(thisDescriptor, resolutionScope, 155 functionDeclaration, 156 resolveSession.getTrace())); 157 } 158 159 getNonDeclaredFunctions(name, result); 160 161 return result; 162 } 163 164 @NotNull 165 protected abstract JetScope getScopeForMemberDeclarationResolution(JetDeclaration declaration); 166 167 protected abstract void getNonDeclaredFunctions(@NotNull Name name, @NotNull Set<FunctionDescriptor> result); 168 169 @NotNull 170 @Override 171 public Set<VariableDescriptor> getProperties(@NotNull Name name) { 172 return propertyDescriptors.fun(name); 173 } 174 175 @NotNull 176 public Set<VariableDescriptor> doGetProperties(@NotNull Name name) { 177 Set<VariableDescriptor> result = Sets.newLinkedHashSet(); 178 179 Collection<JetProperty> declarations = declarationProvider.getPropertyDeclarations(name); 180 for (JetProperty propertyDeclaration : declarations) { 181 JetScope resolutionScope = getScopeForMemberDeclarationResolution(propertyDeclaration); 182 PropertyDescriptor propertyDescriptor = 183 resolveSession.getInjector().getDescriptorResolver().resolvePropertyDescriptor(thisDescriptor, resolutionScope, 184 propertyDeclaration, 185 resolveSession.getTrace()); 186 result.add(propertyDescriptor); 187 resolveSession.getInjector().getAnnotationResolver().resolveAnnotationsArguments(propertyDescriptor, resolveSession.getTrace(), resolutionScope); 188 } 189 190 // Objects are also properties 191 Collection<JetClassOrObject> classOrObjectDeclarations = declarationProvider.getClassOrObjectDeclarations(name); 192 for (JetClassOrObject classOrObjectDeclaration : classOrObjectDeclarations) { 193 if (declaresObjectOrEnumConstant(classOrObjectDeclaration)) { 194 ClassDescriptor classifier = getObjectDescriptor(name); 195 if (classifier == null) { 196 throw new IllegalStateException("Object declaration " + name + " found in the DeclarationProvider " + declarationProvider + " but not in the scope " + this); 197 } 198 VariableDescriptor propertyDescriptor = resolveSession.getInjector().getDescriptorResolver() 199 .resolveObjectDeclaration(thisDescriptor, classOrObjectDeclaration, classifier, resolveSession.getTrace()); 200 result.add(propertyDescriptor); 201 } 202 } 203 204 getNonDeclaredProperties(name, result); 205 206 return result; 207 } 208 209 protected abstract void getNonDeclaredProperties(@NotNull Name name, @NotNull Set<VariableDescriptor> result); 210 211 @NotNull 212 @Override 213 public Collection<ClassDescriptor> getObjectDescriptors() { 214 return allDescriptors.compute().objects; 215 } 216 217 @Override 218 public VariableDescriptor getLocalVariable(@NotNull Name name) { 219 return null; 220 } 221 222 @NotNull 223 @Override 224 public DeclarationDescriptor getContainingDeclaration() { 225 return thisDescriptor; 226 } 227 228 @NotNull 229 @Override 230 public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) { 231 // A member scope has no labels 232 return Collections.emptySet(); 233 } 234 235 @Override 236 public PropertyDescriptor getPropertyByFieldReference(@NotNull Name fieldName) { 237 throw new UnsupportedOperationException(); // TODO 238 } 239 240 @NotNull 241 @Override 242 public Collection<DeclarationDescriptor> getAllDescriptors() { 243 return allDescriptors.compute().all; 244 } 245 246 @NotNull 247 private AllDescriptors computeAllDescriptors() { 248 AllDescriptors result = new AllDescriptors(); 249 for (JetDeclaration declaration : declarationProvider.getAllDeclarations()) { 250 if (declaration instanceof JetEnumEntry) { 251 JetEnumEntry jetEnumEntry = (JetEnumEntry) declaration; 252 Name name = safeNameForLazyResolve(jetEnumEntry); 253 if (name != null) { 254 result.all.addAll(getProperties(name)); 255 result.objects.add(getObjectDescriptor(name)); 256 } 257 } 258 else if (declaration instanceof JetObjectDeclaration) { 259 JetObjectDeclaration objectDeclaration = (JetObjectDeclaration) declaration; 260 Name name = safeNameForLazyResolve(objectDeclaration.getNameAsDeclaration()); 261 if (name != null) { 262 result.all.addAll(getProperties(name)); 263 result.objects.add(getObjectDescriptor(name)); 264 } 265 } 266 else if (declaration instanceof JetClassOrObject) { 267 JetClassOrObject classOrObject = (JetClassOrObject) declaration; 268 Name name = safeNameForLazyResolve(classOrObject.getNameAsName()); 269 if (name != null) { 270 result.all.addAll(classDescriptors.fun(name)); 271 } 272 } 273 else if (declaration instanceof JetFunction) { 274 JetFunction function = (JetFunction) declaration; 275 result.all.addAll(getFunctions(safeNameForLazyResolve(function))); 276 } 277 else if (declaration instanceof JetProperty) { 278 JetProperty property = (JetProperty) declaration; 279 result.all.addAll(getProperties(safeNameForLazyResolve(property))); 280 } 281 else if (declaration instanceof JetParameter) { 282 JetParameter parameter = (JetParameter) declaration; 283 Name name = safeNameForLazyResolve(parameter); 284 result.all.addAll(getProperties(name)); 285 } 286 else if (declaration instanceof JetTypedef || declaration instanceof JetMultiDeclaration) { 287 // Do nothing for typedefs as they are not supported. 288 // MultiDeclarations are not supported on global level too. 289 } 290 else { 291 throw new IllegalArgumentException("Unsupported declaration kind: " + declaration); 292 } 293 } 294 addExtraDescriptors(result.all); 295 return result; 296 } 297 298 protected abstract void addExtraDescriptors(@NotNull Collection<DeclarationDescriptor> result); 299 300 @NotNull 301 @Override 302 public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() { 303 ReceiverParameterDescriptor receiver = getImplicitReceiver(); 304 if (receiver != null) { 305 return Collections.singletonList(receiver); 306 } 307 return Collections.emptyList(); 308 } 309 310 @Nullable 311 protected abstract ReceiverParameterDescriptor getImplicitReceiver(); 312 313 // Do not change this, override in concrete subclasses: 314 // it is very easy to compromise laziness of this class, and fail all the debugging 315 // a generic implementation can't do this properly 316 @Override 317 public abstract String toString(); 318 319 @NotNull 320 @Override 321 public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() { 322 return getAllDescriptors(); 323 } 324}