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.java.resolver;
018
019 import com.intellij.openapi.vfs.VirtualFile;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.descriptors.serialization.*;
023 import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedClassDescriptor;
024 import org.jetbrains.jet.descriptors.serialization.descriptors.DeserializedPackageMemberScope;
025 import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
026 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
027 import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
028 import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
029 import org.jetbrains.jet.lang.resolve.name.FqName;
030 import org.jetbrains.jet.lang.resolve.name.Name;
031 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
032
033 import javax.inject.Inject;
034 import java.util.Collection;
035
036 import static org.jetbrains.jet.lang.resolve.java.AbiVersionUtil.isAbiVersionCompatible;
037 import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES;
038 import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES;
039 import static org.jetbrains.jet.lang.resolve.java.resolver.DeserializedResolverUtils.kotlinFqNameToJavaFqName;
040
041 public final class DeserializedDescriptorResolver {
042 private AnnotationDescriptorDeserializer annotationDeserializer;
043
044 private final LockBasedStorageManager storageManager = new LockBasedStorageManager();
045
046 private JavaNamespaceResolver javaNamespaceResolver;
047
048 private JavaClassResolver javaClassResolver;
049
050 private ErrorReporter errorReporter;
051
052 @NotNull
053 private final DescriptorFinder javaDescriptorFinder = new DescriptorFinder() {
054 @Nullable
055 @Override
056 public ClassDescriptor findClass(@NotNull ClassId classId) {
057 return javaClassResolver.resolveClass(kotlinFqNameToJavaFqName(classId.asSingleFqName()), INCLUDE_KOTLIN_SOURCES);
058 }
059
060 @Nullable
061 @Override
062 public NamespaceDescriptor findPackage(@NotNull FqName name) {
063 return javaNamespaceResolver.resolveNamespace(name, IGNORE_KOTLIN_SOURCES);
064 }
065
066 @NotNull
067 @Override
068 public Collection<Name> getClassNames(@NotNull FqName packageName) {
069 return javaNamespaceResolver.getClassNamesInPackage(packageName);
070 }
071 };
072
073 @Inject
074 public void setAnnotationDeserializer(AnnotationDescriptorDeserializer annotationDeserializer) {
075 this.annotationDeserializer = annotationDeserializer;
076 }
077
078 @Inject
079 public void setJavaNamespaceResolver(JavaNamespaceResolver javaNamespaceResolver) {
080 this.javaNamespaceResolver = javaNamespaceResolver;
081 }
082
083 @Inject
084 public void setJavaClassResolver(JavaClassResolver javaClassResolver) {
085 this.javaClassResolver = javaClassResolver;
086 }
087
088 @Inject
089 public void setErrorReporter(ErrorReporter errorReporter) {
090 this.errorReporter = errorReporter;
091 }
092
093 @Nullable
094 public ClassDescriptor resolveClass(@NotNull ClassId id, @NotNull VirtualFile file) {
095 String[] data = readData(file);
096 if (data != null) {
097 ClassData classData = JavaProtoBufUtil.readClassDataFrom(data);
098 return createDeserializedClass(classData, id);
099 }
100 return null;
101 }
102
103 @Nullable
104 public JetScope createKotlinPackageScope(@NotNull NamespaceDescriptor descriptor, @NotNull VirtualFile file) {
105 String[] data = readData(file);
106 if (data != null) {
107 PackageData packageData = JavaProtoBufUtil.readPackageDataFrom(data);
108 return new DeserializedPackageMemberScope(storageManager, descriptor, annotationDeserializer, javaDescriptorFinder,
109 packageData);
110 }
111 return null;
112 }
113
114 @Nullable
115 private ClassDescriptor createDeserializedClass(@NotNull ClassData classData, @NotNull ClassId classId) {
116 DeclarationDescriptor owner = classId.isTopLevelClass()
117 ? javaNamespaceResolver.resolveNamespace(classId.getPackageFqName(), INCLUDE_KOTLIN_SOURCES)
118 : javaClassResolver.resolveClass(kotlinFqNameToJavaFqName(classId.getOuterClassId().asSingleFqName()),
119 IGNORE_KOTLIN_SOURCES);
120 assert owner != null : "No owner found for " + classId;
121
122 return new DeserializedClassDescriptor(classId, storageManager, owner, classData.getNameResolver(),
123 annotationDeserializer, javaDescriptorFinder, classData.getClassProto(), null);
124 }
125
126 @Nullable
127 private String[] readData(@NotNull VirtualFile virtualFile) {
128 KotlinClassFileHeader header = KotlinClassFileHeader.readKotlinHeaderFromClassFile(virtualFile);
129 int version = header.getVersion();
130 if (!isAbiVersionCompatible(version) && header.getType() != KotlinClassFileHeader.HeaderType.NONE) {
131 errorReporter.reportIncompatibleAbiVersion(header.getFqName(), virtualFile, version);
132 return null;
133 }
134 return header.getAnnotationData();
135 }
136 }