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> simpleNames = 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> getSimpleNames() {
057 return simpleNames.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 simpleNames.intern(name.asString());
067 }
068
069 public int getFqNameIndex(@NotNull ClassOrPackageFragmentDescriptor descriptor) {
070 QualifiedName.Builder builder = QualifiedName.newBuilder();
071 if (descriptor instanceof ClassDescriptor) {
072 builder.setKind(QualifiedName.Kind.CLASS);
073 }
074 builder.setShortName(getSimpleNameIndex(descriptor.getName()));
075
076 DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
077 if (containingDeclaration instanceof PackageFragmentDescriptor) {
078 PackageFragmentDescriptor fragment = (PackageFragmentDescriptor) containingDeclaration;
079 if (!fragment.getFqName().isRoot()) {
080 builder.setParentQualifiedName(getFqNameIndex(fragment.getFqName()));
081 }
082 }
083 else if (containingDeclaration instanceof ClassDescriptor) {
084 ClassDescriptor outerClass = (ClassDescriptor) containingDeclaration;
085 builder.setParentQualifiedName(getFqNameIndex(outerClass));
086 }
087 else {
088 throw new IllegalStateException("FQ names are only stored for top-level or inner classes: " + descriptor);
089 }
090
091 return qualifiedNames.intern(builder);
092 }
093
094 public int getFqNameIndex(@NotNull FqName fqName) {
095 int result = -1;
096 for (Name segment : fqName.pathSegments()) {
097 QualifiedName.Builder builder = QualifiedName.newBuilder();
098 builder.setShortName(getSimpleNameIndex(segment));
099 if (result != -1) {
100 builder.setParentQualifiedName(result);
101 }
102 result = qualifiedNames.intern(builder);
103 }
104 return result;
105 }
106 }