001    /*
002     * Copyright 2010-2015 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.kotlin.load.kotlin;
018    
019    import kotlin.jvm.functions.Function0;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.kotlin.descriptors.ClassDescriptor;
023    import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
024    import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
025    import org.jetbrains.kotlin.name.Name;
026    import org.jetbrains.kotlin.resolve.scopes.JetScope;
027    import org.jetbrains.kotlin.serialization.PackageData;
028    import org.jetbrains.kotlin.serialization.deserialization.DeserializationComponents;
029    import org.jetbrains.kotlin.serialization.deserialization.ErrorReporter;
030    import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPackageMemberScope;
031    import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil;
032    
033    import javax.inject.Inject;
034    import java.util.Collection;
035    import java.util.Collections;
036    
037    import static org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.Kind.CLASS;
038    import static org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.Kind.PACKAGE_FACADE;
039    
040    public final class DeserializedDescriptorResolver {
041        private final ErrorReporter errorReporter;
042        private DeserializationComponents components;
043    
044        public DeserializedDescriptorResolver(@NotNull ErrorReporter errorReporter) {
045            this.errorReporter = errorReporter;
046        }
047    
048        @Inject
049        public void setComponents(@NotNull DeserializationComponentsForJava context) {
050            this.components = context.getComponents();
051        }
052    
053        @Nullable
054        public ClassDescriptor resolveClass(@NotNull KotlinJvmBinaryClass kotlinClass) {
055            String[] data = readData(kotlinClass, CLASS);
056            if (data != null) {
057                return components.getClassDeserializer().deserializeClass(
058                        kotlinClass.getClassId(), JvmProtoBufUtil.readClassDataFrom(data)
059                );
060            }
061            return null;
062        }
063    
064        @Nullable
065        public JetScope createKotlinPackageScope(@NotNull PackageFragmentDescriptor descriptor, @NotNull KotlinJvmBinaryClass kotlinClass) {
066            String[] data = readData(kotlinClass, PACKAGE_FACADE);
067            if (data != null) {
068                //all classes are included in java scope
069                PackageData packageData = JvmProtoBufUtil.readPackageDataFrom(data);
070                return new DeserializedPackageMemberScope(
071                        descriptor, packageData.getPackageProto(), packageData.getNameResolver(), components,
072                        new Function0<Collection<Name>>() {
073                            @Override
074                            public Collection<Name> invoke() {
075                                return Collections.emptyList();
076                            }
077                        }
078                );
079            }
080            return null;
081        }
082    
083        @Nullable
084        public String[] readData(@NotNull KotlinJvmBinaryClass kotlinClass, @NotNull KotlinClassHeader.Kind expectedKind) {
085            KotlinClassHeader header = kotlinClass.getClassHeader();
086            if (!header.getIsCompatibleAbiVersion()) {
087                errorReporter.reportIncompatibleAbiVersion(kotlinClass.getClassId(), kotlinClass.getLocation(), header.getVersion());
088            }
089            else if (header.getKind() == expectedKind) {
090                return header.getAnnotationData();
091            }
092    
093            return null;
094        }
095    }