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