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 org.jetbrains.annotations.NotNull;
020    import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
021    import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
022    import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
023    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
024    import org.jetbrains.jet.lang.resolve.name.FqName;
025    import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
026    
027    import java.util.Collection;
028    
029    public class ClassSerializationUtil {
030        private ClassSerializationUtil() {
031        }
032    
033        public interface Sink {
034            void writeClass(@NotNull ClassDescriptor classDescriptor, @NotNull ProtoBuf.Class classProto);
035        }
036    
037        public static void serializeClass(@NotNull ClassDescriptor classDescriptor, @NotNull DescriptorSerializer serializer, @NotNull Sink sink) {
038            ProtoBuf.Class classProto = serializer.classProto(classDescriptor).build();
039            sink.writeClass(classDescriptor, classProto);
040    
041            serializeClasses(classDescriptor.getUnsubstitutedInnerClassesScope().getAllDescriptors(), serializer, sink);
042    
043            serializeClasses(classDescriptor.getUnsubstitutedInnerClassesScope().getObjectDescriptors(), serializer, sink);
044    
045            ClassDescriptor classObjectDescriptor = classDescriptor.getClassObjectDescriptor();
046            if (classObjectDescriptor != null) {
047                serializeClass(classObjectDescriptor, serializer, sink);
048            }
049        }
050    
051        public static void serializeClasses(
052                @NotNull Collection<? extends DeclarationDescriptor> descriptors,
053                @NotNull DescriptorSerializer serializer,
054                @NotNull Sink sink
055        ) {
056            for (DeclarationDescriptor descriptor : descriptors) {
057                if (descriptor instanceof ClassDescriptor) {
058                    serializeClass((ClassDescriptor) descriptor, serializer, sink);
059                }
060            }
061        }
062    
063        @NotNull
064        public static ClassId getClassId(@NotNull ClassDescriptor classDescriptor) {
065            DeclarationDescriptor containingDeclaration = classDescriptor.getContainingDeclaration();
066            if (containingDeclaration instanceof NamespaceDescriptor) {
067                NamespaceDescriptor namespaceDescriptor = (NamespaceDescriptor) containingDeclaration;
068                return new ClassId(getPackageFqName(namespaceDescriptor), FqNameUnsafe.topLevel(classDescriptor.getName()));
069            }
070            // it must be a nested class
071            ClassDescriptor outer = (ClassDescriptor) containingDeclaration;
072            ClassId outerId = getClassId(outer);
073            return outerId.createNestedClassId(classDescriptor.getName());
074        }
075    
076        @NotNull
077        public static FqName getPackageFqName(@NotNull NamespaceDescriptor namespaceDescriptor) {
078            if (DescriptorUtils.isRootNamespace(namespaceDescriptor)) return FqName.ROOT;
079    
080            NamespaceDescriptor parent = (NamespaceDescriptor) namespaceDescriptor.getContainingDeclaration();
081            return getPackageFqName(parent).child(namespaceDescriptor.getName());
082        }
083    }