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
017 package org.jetbrains.jet.descriptors.serialization.descriptors;
018
019 import com.intellij.openapi.util.Computable;
020 import com.intellij.util.Function;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.jet.descriptors.serialization.DescriptorDeserializer;
024 import org.jetbrains.jet.descriptors.serialization.Flags;
025 import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
026 import org.jetbrains.jet.lang.descriptors.*;
027 import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNotNull;
028 import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue;
029 import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
030 import org.jetbrains.jet.lang.resolve.name.LabelName;
031 import org.jetbrains.jet.lang.resolve.name.Name;
032 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
033
034 import java.util.*;
035
036 import static org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager.ReferenceKind.STRONG;
037
038 public abstract class DeserializedMemberScope implements JetScope {
039
040 private static final Filter<ProtoBuf.Callable.CallableKind> FUNCTION = new Filter<ProtoBuf.Callable.CallableKind>() {
041 @Override
042 public boolean accept(ProtoBuf.Callable.CallableKind value) {
043 return value == ProtoBuf.Callable.CallableKind.FUN;
044 }
045 };
046 private static final Filter<ProtoBuf.Callable.CallableKind> PROPERTY = new Filter<ProtoBuf.Callable.CallableKind>() {
047 @Override
048 public boolean accept(ProtoBuf.Callable.CallableKind value) {
049 return value == ProtoBuf.Callable.CallableKind.VAL ||
050 value == ProtoBuf.Callable.CallableKind.VAR ||
051 value == ProtoBuf.Callable.CallableKind.OBJECT_PROPERTY;
052 }
053 };
054
055 private final DeclarationDescriptor containingDeclaration;
056 private final DescriptorDeserializer deserializer;
057
058 // Never modified after creation
059 private final Map<Name, List<ProtoBuf.Callable>> membersProtos;
060
061 private final MemoizedFunctionToNotNull<Name, Collection<FunctionDescriptor>> functions;
062 private final MemoizedFunctionToNotNull<Name, Collection<VariableDescriptor>> properties;
063 private final NotNullLazyValue<Collection<DeclarationDescriptor>> allDescriptors;
064 private final NotNullLazyValue<Collection<ClassDescriptor>> objectDescriptors;
065
066 public DeserializedMemberScope(
067 @NotNull StorageManager storageManager,
068 @NotNull DeclarationDescriptor containingDeclaration,
069 @NotNull DescriptorDeserializer deserializer,
070 @NotNull List<ProtoBuf.Callable> membersList
071 ) {
072 this.containingDeclaration = containingDeclaration;
073 this.deserializer = deserializer;
074
075 this.membersProtos = groupByName(membersList);
076 this.functions = storageManager.createMemoizedFunction(new Function<Name, Collection<FunctionDescriptor>>() {
077 @Override
078 public Collection<FunctionDescriptor> fun(Name name) {
079 return computeFunctions(name);
080 }
081 }, STRONG);
082 this.properties = storageManager.createMemoizedFunction(new Function<Name, Collection<VariableDescriptor>>() {
083 @Override
084 public Collection<VariableDescriptor> fun(Name name) {
085 return computeProperties(name);
086 }
087 }, STRONG);
088 this.allDescriptors = storageManager.createLazyValue(new Computable<Collection<DeclarationDescriptor>>() {
089 @Override
090 public Collection<DeclarationDescriptor> compute() {
091 return computeAllDescriptors();
092 }
093 });
094 this.objectDescriptors = storageManager.createLazyValue(new Computable<Collection<ClassDescriptor>>() {
095 @Override
096 public Collection<ClassDescriptor> compute() {
097 return computeAllObjectDescriptors();
098 }
099 });
100 }
101
102 @NotNull
103 private Map<Name, List<ProtoBuf.Callable>> groupByName(@NotNull Collection<ProtoBuf.Callable> membersList) {
104 Map<Name, List<ProtoBuf.Callable>> map = new HashMap<Name, List<ProtoBuf.Callable>>();
105 for (ProtoBuf.Callable memberProto : membersList) {
106 Name name = deserializer.getNameResolver().getName(memberProto.getName());
107 List<ProtoBuf.Callable> protos = map.get(name);
108 if (protos == null) {
109 protos = new ArrayList<ProtoBuf.Callable>(1);
110 map.put(name, protos);
111 }
112 protos.add(memberProto);
113 }
114 return map;
115 }
116
117 @NotNull
118 private <D extends CallableMemberDescriptor> Collection<D> computeMembersByName(Name name, Filter<ProtoBuf.Callable.CallableKind> callableKind) {
119 List<ProtoBuf.Callable> memberProtos = membersProtos.get(name);
120
121 Collection<D> descriptors = new LinkedHashSet<D>(memberProtos != null ? memberProtos.size() : 0);
122 if (memberProtos != null) {
123 for (ProtoBuf.Callable memberProto : memberProtos) {
124 if (callableKind.accept(Flags.CALLABLE_KIND.get(memberProto.getFlags()))) {
125 //noinspection unchecked
126 descriptors.add((D) deserializer.loadCallable(memberProto));
127 }
128 }
129 }
130 return descriptors;
131 }
132
133 @NotNull
134 private Collection<FunctionDescriptor> computeFunctions(@NotNull Name name) {
135 Collection<FunctionDescriptor> descriptors = computeMembersByName(name, FUNCTION);
136 computeNonDeclaredFunctions(name, descriptors);
137 return descriptors;
138 }
139
140 protected void computeNonDeclaredFunctions(@NotNull Name name, @NotNull Collection<FunctionDescriptor> functions) {
141 }
142
143 @NotNull
144 @Override
145 public final Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
146 return functions.fun(name);
147 }
148
149 @NotNull
150 private Collection<VariableDescriptor> computeProperties(@NotNull Name name) {
151 Collection<PropertyDescriptor> descriptors = computeMembersByName(name, PROPERTY);
152 computeNonDeclaredProperties(name, descriptors);
153 //noinspection unchecked
154 return (Collection) descriptors;
155 }
156
157 protected void computeNonDeclaredProperties(@NotNull Name name, @NotNull Collection<PropertyDescriptor> descriptors) {
158 }
159
160 @NotNull
161 @Override
162 public Collection<VariableDescriptor> getProperties(@NotNull Name name) {
163 return properties.fun(name);
164 }
165
166 @Nullable
167 @Override
168 public final ClassifierDescriptor getClassifier(@NotNull Name name) {
169 return getClassDescriptor(name);
170 }
171
172 @Nullable
173 protected abstract ClassifierDescriptor getClassDescriptor(@NotNull Name name);
174
175 protected abstract void addAllClassDescriptors(@NotNull Collection<DeclarationDescriptor> result);
176
177 @Nullable
178 @Override
179 public abstract ClassDescriptor getObjectDescriptor(@NotNull Name name);
180
181 @NotNull
182 protected abstract Collection<ClassDescriptor> computeAllObjectDescriptors();
183
184 @NotNull
185 @Override
186 public Collection<ClassDescriptor> getObjectDescriptors() {
187 return objectDescriptors.compute();
188 }
189
190 @Nullable
191 @Override
192 public NamespaceDescriptor getNamespace(@NotNull Name name) {
193 return null;
194 }
195
196 @Nullable
197 @Override
198 public VariableDescriptor getLocalVariable(@NotNull Name name) {
199 return null;
200 }
201
202 @NotNull
203 @Override
204 public DeclarationDescriptor getContainingDeclaration() {
205 return containingDeclaration;
206 }
207
208 @NotNull
209 @Override
210 public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) {
211 throw new UnsupportedOperationException("Should not be called");
212 }
213
214 @Nullable
215 @Override
216 public PropertyDescriptor getPropertyByFieldReference(@NotNull Name fieldName) {
217 throw new UnsupportedOperationException("Should not be called");
218 }
219
220 private Collection<DeclarationDescriptor> computeAllDescriptors() {
221 Collection<DeclarationDescriptor> result = new LinkedHashSet<DeclarationDescriptor>(0);
222
223 for (Name name : membersProtos.keySet()) {
224 result.addAll(getFunctions(name));
225 result.addAll(getProperties(name));
226 }
227
228 addNonDeclaredDescriptors(result);
229
230 addAllClassDescriptors(result);
231
232 return result;
233 }
234
235 protected abstract void addNonDeclaredDescriptors(@NotNull Collection<DeclarationDescriptor> result);
236
237 @NotNull
238 @Override
239 public final Collection<DeclarationDescriptor> getAllDescriptors() {
240 return allDescriptors.compute();
241 }
242
243 @NotNull
244 @Override
245 public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
246 ReceiverParameterDescriptor receiver = getImplicitReceiver();
247 if (receiver != null) {
248 return Collections.singletonList(receiver);
249 }
250 return Collections.emptyList();
251 }
252
253 @Nullable
254 protected abstract ReceiverParameterDescriptor getImplicitReceiver();
255
256 @NotNull
257 @Override
258 public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
259 return getAllDescriptors();
260 }
261
262 private interface Filter<T> {
263 boolean accept(T value);
264 }
265
266 }