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.serialization.deserialization;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.kotlin.name.ClassId;
021 import org.jetbrains.kotlin.name.FqName;
022 import org.jetbrains.kotlin.name.Name;
023 import org.jetbrains.kotlin.serialization.ProtoBuf;
024 import org.jetbrains.kotlin.utils.UtilsPackage;
025
026 import java.io.IOException;
027 import java.io.InputStream;
028 import java.util.LinkedList;
029
030 import static org.jetbrains.kotlin.serialization.ProtoBuf.QualifiedNameTable.QualifiedName;
031
032 public class NameResolver {
033 @NotNull
034 public static NameResolver read(@NotNull InputStream in) {
035 try {
036 ProtoBuf.StringTable simpleNames = ProtoBuf.StringTable.parseDelimitedFrom(in);
037 ProtoBuf.QualifiedNameTable qualifiedNames = ProtoBuf.QualifiedNameTable.parseDelimitedFrom(in);
038 return new NameResolver(simpleNames, qualifiedNames);
039 }
040 catch (IOException e) {
041 throw UtilsPackage.rethrow(e);
042 }
043 }
044
045 private final ProtoBuf.StringTable strings;
046 private final ProtoBuf.QualifiedNameTable qualifiedNames;
047
048 public NameResolver(
049 @NotNull ProtoBuf.StringTable strings,
050 @NotNull ProtoBuf.QualifiedNameTable qualifiedNames
051 ) {
052 this.strings = strings;
053 this.qualifiedNames = qualifiedNames;
054 }
055
056 @NotNull
057 public String getString(int index) {
058 return strings.getString(index);
059 }
060
061 @NotNull
062 public Name getName(int index) {
063 return Name.guess(strings.getString(index));
064 }
065
066 @NotNull
067 public ClassId getClassId(int index) {
068 LinkedList<String> packageFqName = new LinkedList<String>();
069 LinkedList<String> relativeClassName = new LinkedList<String>();
070 boolean local = false;
071
072 while (index != -1) {
073 QualifiedName proto = qualifiedNames.getQualifiedName(index);
074 String shortName = strings.getString(proto.getShortName());
075 switch (proto.getKind()) {
076 case CLASS:
077 relativeClassName.addFirst(shortName);
078 break;
079 case PACKAGE:
080 packageFqName.addFirst(shortName);
081 break;
082 case LOCAL:
083 relativeClassName.addFirst(shortName);
084 local = true;
085 break;
086 }
087
088 index = proto.getParentQualifiedName();
089 }
090
091 return new ClassId(FqName.fromSegments(packageFqName), FqName.fromSegments(relativeClassName), local);
092 }
093
094 @NotNull
095 public FqName getFqName(int index) {
096 QualifiedName qualifiedName = qualifiedNames.getQualifiedName(index);
097 Name shortName = getName(qualifiedName.getShortName());
098 if (!qualifiedName.hasParentQualifiedName()) {
099 return FqName.topLevel(shortName);
100 }
101 return getFqName(qualifiedName.getParentQualifiedName()).child(shortName);
102 }
103 }