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.ClassDescriptor;
022 import org.jetbrains.jet.lang.descriptors.ClassOrNamespaceDescriptor;
023 import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
024 import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
025 import org.jetbrains.jet.lang.resolve.DescriptorUtils;
026 import org.jetbrains.jet.lang.resolve.name.FqName;
027 import org.jetbrains.jet.lang.resolve.name.Name;
028
029 import java.util.List;
030
031 import static org.jetbrains.jet.descriptors.serialization.ProtoBuf.QualifiedNameTable.QualifiedName;
032
033 public class NameTable {
034 public static final TObjectHashingStrategy<QualifiedName.Builder> QUALIFIED_NAME_BUILDER_HASHING =
035 new TObjectHashingStrategy<ProtoBuf.QualifiedNameTable.QualifiedName.Builder>() {
036 @Override
037 public int computeHashCode(QualifiedName.Builder object) {
038 int result = 13;
039 result = 31 * result + object.getParentQualifiedName();
040 result = 31 * result + object.getShortName();
041 result = 31 * result + object.getKind().hashCode();
042 return result;
043 }
044
045 @Override
046 public boolean equals(QualifiedName.Builder o1, QualifiedName.Builder o2) {
047 return o1.getParentQualifiedName() == o2.getParentQualifiedName()
048 && o1.getShortName() == o2.getShortName()
049 && o1.getKind() == o2.getKind();
050 }
051 };
052
053 private final Interner<String> simpleNames = new Interner<String>();
054 private final Interner<QualifiedName.Builder> qualifiedNames = new Interner<QualifiedName.Builder>(QUALIFIED_NAME_BUILDER_HASHING);
055
056 public NameTable() {
057 }
058
059 @NotNull
060 public List<String> getSimpleNames() {
061 return simpleNames.getAllInternedObjects();
062 }
063
064 @NotNull
065 public List<QualifiedName.Builder> getFqNames() {
066 return qualifiedNames.getAllInternedObjects();
067 }
068
069 public int getSimpleNameIndex(@NotNull Name name) {
070 return simpleNames.intern(name.asString());
071 }
072
073 public int getFqNameIndex(@NotNull ClassOrNamespaceDescriptor 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 NamespaceDescriptor) {
082 NamespaceDescriptor namespaceDescriptor = (NamespaceDescriptor) containingDeclaration;
083 if (!DescriptorUtils.isRootNamespace(namespaceDescriptor)) {
084 builder.setParentQualifiedName(getFqNameIndex(namespaceDescriptor));
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 }