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