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;
018
019 import kotlin.Function0;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.descriptors.serialization.context.DeserializationContextWithTypes;
023 import org.jetbrains.jet.descriptors.serialization.descriptors.*;
024 import org.jetbrains.jet.lang.descriptors.*;
025 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
026 import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl;
027 import org.jetbrains.jet.lang.descriptors.impl.PropertyGetterDescriptorImpl;
028 import org.jetbrains.jet.lang.descriptors.impl.PropertySetterDescriptorImpl;
029 import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
030 import org.jetbrains.jet.lang.resolve.DescriptorFactory;
031 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
032 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
033
034 import java.util.ArrayList;
035 import java.util.Collections;
036 import java.util.List;
037
038 import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.Callable;
039 import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.TypeParameter;
040 import static org.jetbrains.jet.descriptors.serialization.SerializationPackage.*;
041
042 public class MemberDeserializer {
043
044 private final DeserializationContextWithTypes context;
045
046 public MemberDeserializer(@NotNull DeserializationContextWithTypes context) {
047 this.context = context;
048 }
049
050 @NotNull
051 public CallableMemberDescriptor loadCallable(@NotNull Callable proto) {
052 Callable.CallableKind callableKind = Flags.CALLABLE_KIND.get(proto.getFlags());
053 switch (callableKind) {
054 case FUN:
055 return loadFunction(proto);
056 case VAL:
057 case VAR:
058 return loadProperty(proto);
059 case CONSTRUCTOR:
060 return loadConstructor(proto);
061 }
062 throw new IllegalArgumentException("Unsupported callable kind: " + callableKind);
063 }
064
065 @NotNull
066 private PropertyDescriptor loadProperty(@NotNull final Callable proto) {
067 final int flags = proto.getFlags();
068
069 DeserializedPropertyDescriptor property = new DeserializedPropertyDescriptor(
070 context.getContainingDeclaration(),
071 null,
072 getAnnotations(proto, flags, AnnotatedCallableKind.PROPERTY),
073 modality(Flags.MODALITY.get(flags)),
074 visibility(Flags.VISIBILITY.get(flags)),
075 Flags.CALLABLE_KIND.get(flags) == Callable.CallableKind.VAR,
076 context.getNameResolver().getName(proto.getName()),
077 SerializationPackage.memberKind(Flags.MEMBER_KIND.get(flags)),
078 proto,
079 context.getNameResolver()
080 );
081
082 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
083 DeserializationContextWithTypes local = context.childContext(property, proto.getTypeParameterList(), typeParameters);
084 property.setType(
085 local.getTypeDeserializer().type(proto.getReturnType()),
086 typeParameters,
087 getExpectedThisObject(),
088 local.getTypeDeserializer().typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null)
089 );
090
091 PropertyGetterDescriptorImpl getter = null;
092 PropertySetterDescriptorImpl setter = null;
093
094 if (Flags.HAS_GETTER.get(flags)) {
095 int getterFlags = proto.getGetterFlags();
096 boolean isNotDefault = proto.hasGetterFlags() && Flags.IS_NOT_DEFAULT.get(getterFlags);
097 if (isNotDefault) {
098 getter = new PropertyGetterDescriptorImpl(property,
099 getAnnotations(proto, getterFlags, AnnotatedCallableKind.PROPERTY_GETTER),
100 modality(Flags.MODALITY.get(getterFlags)),
101 visibility(Flags.VISIBILITY.get(getterFlags)),
102 isNotDefault, !isNotDefault,
103 property.getKind(), null);
104 }
105 else {
106 getter = DescriptorFactory.createDefaultGetter(property);
107 }
108 getter.initialize(property.getReturnType());
109 }
110
111 if (Flags.HAS_SETTER.get(flags)) {
112 int setterFlags = proto.getSetterFlags();
113 boolean isNotDefault = proto.hasSetterFlags() && Flags.IS_NOT_DEFAULT.get(setterFlags);
114 if (isNotDefault) {
115 setter = new PropertySetterDescriptorImpl(property,
116 getAnnotations(proto, setterFlags, AnnotatedCallableKind.PROPERTY_SETTER),
117 modality(Flags.MODALITY.get(setterFlags)),
118 visibility(Flags.VISIBILITY.get(setterFlags)), isNotDefault,
119 !isNotDefault,
120 property.getKind(), null);
121 DeserializationContextWithTypes setterLocal = local.childContext(setter, Collections.<TypeParameter>emptyList(),
122 Collections.<TypeParameterDescriptor>emptyList());
123 List<ValueParameterDescriptor> valueParameters
124 = setterLocal.getDeserializer().valueParameters(proto, AnnotatedCallableKind.PROPERTY_SETTER);
125 assert valueParameters.size() == 1 : "Property setter should have a single value parameter: " + setter;
126 setter.initialize(valueParameters.get(0));
127 }
128 else {
129 setter = DescriptorFactory.createDefaultSetter(property);
130 }
131 }
132
133 if (Flags.HAS_CONSTANT.get(flags)) {
134 property.setCompileTimeInitializer(
135 context.getStorageManager().createNullableLazyValue(new Function0<CompileTimeConstant<?>>() {
136 @Nullable
137 @Override
138 public CompileTimeConstant<?> invoke() {
139 DeclarationDescriptor containingDeclaration = context.getContainingDeclaration();
140 assert containingDeclaration instanceof ClassOrPackageFragmentDescriptor
141 : "Only members in classes or package fragments should be serialized: " + containingDeclaration;
142 return context.getConstantLoader().loadPropertyConstant(
143 (ClassOrPackageFragmentDescriptor) containingDeclaration, proto,
144 context.getNameResolver(), AnnotatedCallableKind.PROPERTY);
145 }
146 })
147 );
148 }
149
150 property.initialize(getter, setter);
151
152 return property;
153 }
154
155 @NotNull
156 private CallableMemberDescriptor loadFunction(@NotNull Callable proto) {
157 int flags = proto.getFlags();
158 DeserializedSimpleFunctionDescriptor function = DeserializedSimpleFunctionDescriptor.create(
159 context.getContainingDeclaration(), proto, context.getAnnotationLoader(), context.getNameResolver()
160 );
161 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
162 DeserializationContextWithTypes local = context.childContext(function, proto.getTypeParameterList(), typeParameters);
163 function.initialize(
164 local.getTypeDeserializer().typeOrNull(proto.hasReceiverType() ? proto.getReceiverType() : null),
165 getExpectedThisObject(),
166 typeParameters,
167 local.getDeserializer().valueParameters(proto, AnnotatedCallableKind.FUNCTION),
168 local.getTypeDeserializer().type(proto.getReturnType()),
169 modality(Flags.MODALITY.get(flags)),
170 visibility(Flags.VISIBILITY.get(flags))
171 );
172 return function;
173 }
174
175 @Nullable
176 private ReceiverParameterDescriptor getExpectedThisObject() {
177 DeclarationDescriptor containingDeclaration = context.getContainingDeclaration();
178 return containingDeclaration instanceof ClassDescriptor
179 ? ((ClassDescriptor) containingDeclaration).getThisAsReceiverParameter() : null;
180 }
181
182 @NotNull
183 private CallableMemberDescriptor loadConstructor(@NotNull Callable proto) {
184 ClassDescriptor classDescriptor = (ClassDescriptor) context.getContainingDeclaration();
185 ConstructorDescriptorImpl descriptor = ConstructorDescriptorImpl.create(
186 classDescriptor,
187 getAnnotations(proto, proto.getFlags(), AnnotatedCallableKind.FUNCTION),
188 // TODO: primary
189 true);
190 List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(proto.getTypeParameterCount());
191 DeserializationContextWithTypes local = context.childContext(descriptor, Collections.<TypeParameter>emptyList(), typeParameters);
192 descriptor.initialize(
193 classDescriptor.getTypeConstructor().getParameters(),
194 local.getDeserializer().valueParameters(proto, AnnotatedCallableKind.FUNCTION),
195 visibility(Flags.VISIBILITY.get(proto.getFlags())),
196 DescriptorUtils.isConstructorOfStaticNestedClass(descriptor)
197 );
198 descriptor.setReturnType(local.getTypeDeserializer().type(proto.getReturnType()));
199 return descriptor;
200 }
201
202 @NotNull
203 private Annotations getAnnotations(@NotNull Callable proto, int flags, @NotNull AnnotatedCallableKind kind) {
204 return getAnnotations(context.getContainingDeclaration(), proto, flags, kind, context.getAnnotationLoader(), context.getNameResolver());
205 }
206
207 public static Annotations getAnnotations(
208 @NotNull DeclarationDescriptor containingDeclaration,
209 @NotNull Callable proto,
210 int flags,
211 @NotNull AnnotatedCallableKind kind,
212 @NotNull AnnotationLoader annotationLoader,
213 @NotNull NameResolver nameResolver
214 ) {
215 assert containingDeclaration instanceof ClassOrPackageFragmentDescriptor
216 : "Only members in classes or package fragments should be serialized: " + containingDeclaration;
217 return Flags.HAS_ANNOTATIONS.get(flags) ? annotationLoader.loadCallableAnnotations(
218 (ClassOrPackageFragmentDescriptor) containingDeclaration, proto, nameResolver, kind) : Annotations.EMPTY;
219 }
220
221 @NotNull
222 public List<DeserializedTypeParameterDescriptor> typeParameters(
223 @NotNull List<TypeParameter> protos,
224 @NotNull TypeDeserializer typeDeserializer
225 ) {
226 List<DeserializedTypeParameterDescriptor> result = new ArrayList<DeserializedTypeParameterDescriptor>(protos.size());
227 for (int i = 0; i < protos.size(); i++) {
228 TypeParameter proto = protos.get(i);
229 DeserializedTypeParameterDescriptor descriptor = new DeserializedTypeParameterDescriptor(
230 context.getStorageManager(),
231 typeDeserializer,
232 proto,
233 context.getContainingDeclaration(),
234 context.getNameResolver().getName(proto.getName()),
235 variance(proto.getVariance()),
236 proto.getReified(),
237 i
238 );
239 result.add(descriptor);
240 }
241 return result;
242 }
243
244 @NotNull
245 private List<ValueParameterDescriptor> valueParameters(@NotNull Callable callable, @NotNull AnnotatedCallableKind kind) {
246 DeclarationDescriptor containerOfCallable = context.getContainingDeclaration().getContainingDeclaration();
247 assert containerOfCallable instanceof ClassOrPackageFragmentDescriptor
248 : "Only members in classes or package fragments should be serialized: " + containerOfCallable;
249 ClassOrPackageFragmentDescriptor classOrPackage = (ClassOrPackageFragmentDescriptor) containerOfCallable;
250
251 List<Callable.ValueParameter> protos = callable.getValueParameterList();
252 List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(protos.size());
253 for (int i = 0; i < protos.size(); i++) {
254 Callable.ValueParameter proto = protos.get(i);
255 result.add(new ValueParameterDescriptorImpl(
256 context.getContainingDeclaration(),
257 null,
258 i,
259 getAnnotations(classOrPackage, callable, kind, proto),
260 context.getNameResolver().getName(proto.getName()),
261 context.getTypeDeserializer().type(proto.getType()),
262 Flags.DECLARES_DEFAULT_VALUE.get(proto.getFlags()),
263 context.getTypeDeserializer().typeOrNull(proto.hasVarargElementType() ? proto.getVarargElementType() : null))
264 );
265 }
266 return result;
267 }
268
269 @NotNull
270 private Annotations getAnnotations(
271 @NotNull ClassOrPackageFragmentDescriptor classOrPackage,
272 @NotNull Callable callable,
273 @NotNull AnnotatedCallableKind kind,
274 @NotNull Callable.ValueParameter valueParameter
275 ) {
276 return Flags.HAS_ANNOTATIONS.get(valueParameter.getFlags()) ? context.getAnnotationLoader()
277 .loadValueParameterAnnotations(classOrPackage, callable, context.getNameResolver(), kind, valueParameter)
278 : Annotations.EMPTY;
279 }
280 }