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