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