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.lang.resolve.kotlin;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.annotations.Nullable;
021    import org.jetbrains.jet.descriptors.serialization.ClassId;
022    import org.jetbrains.jet.descriptors.serialization.DescriptorFinder;
023    import org.jetbrains.jet.descriptors.serialization.JavaProtoBufUtil;
024    import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedClassDescriptor;
025    import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPackageMemberScope;
026    import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
027    import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
028    import org.jetbrains.jet.lang.resolve.java.resolver.ErrorReporter;
029    import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassResolver;
030    import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver;
031    import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
032    import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader;
033    import org.jetbrains.jet.lang.resolve.name.FqName;
034    import org.jetbrains.jet.lang.resolve.name.Name;
035    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
036    import org.jetbrains.jet.storage.LockBasedStorageManager;
037    
038    import javax.inject.Inject;
039    import java.util.Collection;
040    
041    import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
042    import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
043    import static org.jetbrains.jet.lang.resolve.kotlin.DeserializedResolverUtils.kotlinFqNameToJavaFqName;
044    
045    public final class DeserializedDescriptorResolver {
046        private AnnotationDescriptorDeserializer annotationDeserializer;
047    
048        private final LockBasedStorageManager storageManager = new LockBasedStorageManager();
049    
050        private JavaNamespaceResolver javaNamespaceResolver;
051    
052        private JavaClassResolver javaClassResolver;
053    
054        private ErrorReporter errorReporter;
055    
056        @NotNull
057        private final DescriptorFinder javaDescriptorFinder = new DescriptorFinder() {
058            @Nullable
059            @Override
060            public ClassDescriptor findClass(@NotNull ClassId classId) {
061                return javaClassResolver.resolveClass(kotlinFqNameToJavaFqName(classId.asSingleFqName()), INCLUDE_KOTLIN_SOURCES);
062            }
063    
064            @Nullable
065            @Override
066            public NamespaceDescriptor findPackage(@NotNull FqName name) {
067                return javaNamespaceResolver.resolveNamespace(name, IGNORE_KOTLIN_SOURCES);
068            }
069    
070            @NotNull
071            @Override
072            public Collection<Name> getClassNames(@NotNull FqName packageName) {
073                return javaNamespaceResolver.getClassNamesInPackage(packageName);
074            }
075        };
076    
077        @Inject
078        public void setAnnotationDeserializer(AnnotationDescriptorDeserializer annotationDeserializer) {
079            this.annotationDeserializer = annotationDeserializer;
080        }
081    
082        @Inject
083        public void setJavaNamespaceResolver(JavaNamespaceResolver javaNamespaceResolver) {
084            this.javaNamespaceResolver = javaNamespaceResolver;
085        }
086    
087        @Inject
088        public void setJavaClassResolver(JavaClassResolver javaClassResolver) {
089            this.javaClassResolver = javaClassResolver;
090        }
091    
092        @Inject
093        public void setErrorReporter(ErrorReporter errorReporter) {
094            this.errorReporter = errorReporter;
095        }
096    
097        @Nullable
098        public ClassDescriptor resolveClass(@NotNull KotlinJvmBinaryClass kotlinClass) {
099            String[] data = readData(kotlinClass);
100            return data == null ? null : new DeserializedClassDescriptor(storageManager, annotationDeserializer, javaDescriptorFinder,
101                                                                         JavaProtoBufUtil.readClassDataFrom(data));
102        }
103    
104        @Nullable
105        public JetScope createKotlinPackageScope(@NotNull NamespaceDescriptor descriptor, @NotNull KotlinJvmBinaryClass kotlinClass) {
106            String[] data = readData(kotlinClass);
107            return data == null ? null : new DeserializedPackageMemberScope(storageManager, descriptor, annotationDeserializer,
108                                                                            javaDescriptorFinder, JavaProtoBufUtil.readPackageDataFrom(data));
109        }
110    
111        @Nullable
112        private String[] readData(@NotNull KotlinJvmBinaryClass kotlinClass) {
113            KotlinClassHeader header = KotlinClassHeader.read(kotlinClass);
114            if (header instanceof SerializedDataHeader) {
115                return ((SerializedDataHeader) header).getAnnotationData();
116            }
117    
118            if (header != null) {
119                errorReporter.reportIncompatibleAbiVersion(kotlinClass, header.getVersion());
120            }
121    
122            return null;
123        }
124    }