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 gnu.trove.TObjectHashingStrategy;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.jet.lang.descriptors.*;
022 import org.jetbrains.jet.lang.resolve.name.FqName;
023 import org.jetbrains.jet.lang.resolve.name.Name;
024
025 import java.util.List;
026
027 import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.QualifiedNameTable.QualifiedName;
028
029 public class NameTable {
030 public static final TObjectHashingStrategy<QualifiedName.Builder> QUALIFIED_NAME_BUILDER_HASHING =
031 new TObjectHashingStrategy<ProtoBuf.QualifiedNameTable.QualifiedName.Builder>() {
032 @Override
033 public int computeHashCode(QualifiedName.Builder object) {
034 int result = 13;
035 result = 31 * result + object.getParentQualifiedName();
036 result = 31 * result + object.getShortName();
037 result = 31 * result + object.getKind().hashCode();
038 return result;
039 }
040
041 @Override
042 public boolean equals(QualifiedName.Builder o1, QualifiedName.Builder o2) {
043 return o1.getParentQualifiedName() == o2.getParentQualifiedName()
044 && o1.getShortName() == o2.getShortName()
045 && o1.getKind() == o2.getKind();
046 }
047 };
048
049 private final Interner<String> strings = new Interner<String>();
050 private final Interner<QualifiedName.Builder> qualifiedNames = new Interner<QualifiedName.Builder>(QUALIFIED_NAME_BUILDER_HASHING);
051
052 public NameTable() {
053 }
054
055 @NotNull
056 public List<String> getStrings() {
057 return strings.getAllInternedObjects();
058 }
059
060 @NotNull
061 public List<QualifiedName.Builder> getFqNames() {
062 return qualifiedNames.getAllInternedObjects();
063 }
064
065 public int getSimpleNameIndex(@NotNull Name name) {
066 return getStringIndex(name.asString());
067 }
068
069 public int getStringIndex(@NotNull String string) {
070 return strings.intern(string);
071 }
072
073 public int getFqNameIndex(@NotNull ClassOrPackageFragmentDescriptor descriptor) {
074 QualifiedName.Builder builder = QualifiedName.newBuilder();
075 if (descriptor instanceof ClassDescriptor) {
076 builder.setKind(QualifiedName.Kind.CLASS);
077 }
078 builder.setShortName(getSimpleNameIndex(descriptor.getName()));
079
080 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
081 if (containingDeclaration instanceof PackageFragmentDescriptor) {
082 PackageFragmentDescriptor fragment = (PackageFragmentDescriptor) containingDeclaration;
083 if (!fragment.getFqName().isRoot()) {
084 builder.setParentQualifiedName(getFqNameIndex(fragment.getFqName()));
085 }
086 }
087 else if (containingDeclaration instanceof ClassDescriptor) {
088 ClassDescriptor outerClass = (ClassDescriptor) containingDeclaration;
089 builder.setParentQualifiedName(getFqNameIndex(outerClass));
090 }
091 else {
092 throw new IllegalStateException("FQ names are only stored for top-level or inner classes: " + descriptor);
093 }
094
095 return qualifiedNames.intern(builder);
096 }
097
098 public int getFqNameIndex(@NotNull FqName fqName) {
099 int result = -1;
100 for (Name segment : fqName.pathSegments()) {
101 QualifiedName.Builder builder = QualifiedName.newBuilder();
102 builder.setShortName(getSimpleNameIndex(segment));
103 if (result != -1) {
104 builder.setParentQualifiedName(result);
105 }
106 result = qualifiedNames.intern(builder);
107 }
108 return result;
109 }
110 }