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 017package org.jetbrains.jet.lang.resolve.name; 018 019import com.google.common.collect.Lists; 020import com.intellij.openapi.util.text.StringUtil; 021import org.jetbrains.annotations.NotNull; 022 023import java.util.List; 024 025public class FqName extends FqNameBase { 026 027 @NotNull 028 public static FqName fromSegments(@NotNull List<String> names) { 029 String fqName = StringUtil.join(names, "."); 030 return new FqName(fqName); 031 } 032 033 public static final FqName ROOT = new FqName(""); 034 035 @NotNull 036 private final FqNameUnsafe fqName; 037 038 // cache 039 private transient FqName parent; 040 041 public FqName(@NotNull String fqName) { 042 this.fqName = new FqNameUnsafe(fqName, this); 043 044 validateFqName(); 045 } 046 047 public FqName(@NotNull FqNameUnsafe fqName) { 048 this.fqName = fqName; 049 050 validateFqName(); 051 } 052 053 private FqName(@NotNull FqNameUnsafe fqName, FqName parent) { 054 this.fqName = fqName; 055 this.parent = parent; 056 057 validateFqName(); 058 } 059 060 061 private void validateFqName() { 062 if (!isValidAfterUnsafeCheck(fqName.asString())) { 063 throw new IllegalArgumentException("incorrect fq name: " + fqName); 064 } 065 } 066 067 /*package*/ static boolean isValidAfterUnsafeCheck(@NotNull String qualifiedName) { 068 // TODO: There's a valid name with escape char `` 069 return qualifiedName.indexOf('<') < 0; 070 } 071 072 @Override 073 @NotNull 074 public String asString() { 075 return fqName.asString(); 076 } 077 078 @NotNull 079 public FqNameUnsafe toUnsafe() { 080 return fqName; 081 } 082 083 public boolean isRoot() { 084 return fqName.isRoot(); 085 } 086 087 @NotNull 088 public FqName parent() { 089 if (parent != null) { 090 return parent; 091 } 092 093 if (isRoot()) { 094 throw new IllegalStateException("root"); 095 } 096 097 parent = new FqName(fqName.parent()); 098 099 return parent; 100 } 101 102 @NotNull 103 public FqName child(@NotNull Name name) { 104 return new FqName(fqName.child(name), this); 105 } 106 107 @NotNull 108 public Name shortName() { 109 return fqName.shortName(); 110 } 111 112 @NotNull 113 public Name shortNameOrSpecial() { 114 return fqName.shortNameOrSpecial(); 115 } 116 117 @NotNull 118 public List<FqName> path() { 119 final List<FqName> path = Lists.newArrayList(); 120 path.add(ROOT); 121 fqName.walk(new FqNameUnsafe.WalkCallback() { 122 @Override 123 public void segment(@NotNull Name shortName, @NotNull FqNameUnsafe fqName) { 124 // TODO: do not validate 125 path.add(new FqName(fqName)); 126 } 127 }); 128 return path; 129 } 130 131 @NotNull 132 public List<Name> pathSegments() { 133 return fqName.pathSegments(); 134 } 135 136 public boolean firstSegmentIs(@NotNull Name segment) { 137 return fqName.firstSegmentIs(segment); 138 } 139 140 public boolean lastSegmentIs(@NotNull Name segment) { 141 return fqName.lastSegmentIs(segment); 142 } 143 144 145 @NotNull 146 public static FqName topLevel(@NotNull Name shortName) { 147 return new FqName(FqNameUnsafe.topLevel(shortName)); 148 } 149 150 151 @Override 152 public String toString() { 153 return fqName.toString(); 154 } 155 156 @Override 157 public boolean equals(Object o) { 158 // generated by Idea 159 if (this == o) return true; 160 if (o == null || getClass() != o.getClass()) return false; 161 162 FqName that = (FqName) o; 163 164 if (fqName != null ? !fqName.equals(that.fqName) : that.fqName != null) return false; 165 166 return true; 167 } 168 169 @Override 170 public int hashCode() { 171 // generated by Idea 172 return fqName != null ? fqName.hashCode() : 0; 173 } 174}