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