FqName class

for type safety, to easier distinguish between:

* short names
* qualified names
* jvm names (slash-separated)
* special names like <root>
* null values that mean "undefined" and "root ns" in different contexts
This commit is contained in:
Stepan Koltsov
2012-03-13 21:51:38 +04:00
parent 15078b1b70
commit 82d77560a2
41 changed files with 434 additions and 222 deletions
@@ -26,6 +26,7 @@ import org.jetbrains.jet.lang.psi.JetImportDirective;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.FqName;
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
import java.util.Collection;
@@ -60,7 +61,7 @@ public class JavaBridgeConfiguration implements ModuleConfiguration {
delegateConfiguration.addDefaultImports(rootScope, directives);
}
public static JavaNamespaceDescriptor createNamespaceDescriptor(String name, String qualifiedName) {
public static JavaNamespaceDescriptor createNamespaceDescriptor(String name, FqName qualifiedName) {
return new JavaNamespaceDescriptor(null, Collections.<AnnotationDescriptor>emptyList(), name, qualifiedName, true);
}
@@ -73,7 +74,7 @@ public class JavaBridgeConfiguration implements ModuleConfiguration {
@Override
public NamespaceDescriptor getTopLevelNamespace(@NotNull String shortName) {
NamespaceDescriptor namespaceDescriptor = javaSemanticServices.getDescriptorResolver().resolveNamespace(shortName);
NamespaceDescriptor namespaceDescriptor = javaSemanticServices.getDescriptorResolver().resolveNamespace(FqName.topLevel(shortName));
if (namespaceDescriptor != null) {
return namespaceDescriptor;
}
@@ -82,7 +83,7 @@ public class JavaBridgeConfiguration implements ModuleConfiguration {
@Override
public void addAllTopLevelNamespacesTo(@NotNull Collection<? super NamespaceDescriptor> topLevelNamespaces) {
NamespaceDescriptor defaultPackage = javaSemanticServices.getDescriptorResolver().resolveNamespace("");
NamespaceDescriptor defaultPackage = javaSemanticServices.getDescriptorResolver().resolveNamespace(FqName.ROOT);
assert defaultPackage != null : "Cannot resolve Java's default package";
for (DeclarationDescriptor declarationDescriptor : defaultPackage.getMemberScope().getAllDescriptors()) {
if (declarationDescriptor instanceof NamespaceDescriptor) {
@@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.FqName;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.constants.*;
import org.jetbrains.jet.lang.resolve.java.alt.AltClassFinder;
@@ -54,7 +55,7 @@ import java.util.*;
*/
public class JavaDescriptorResolver {
public static String JAVA_ROOT = "<java_root>";
public static final String JAVA_ROOT = "<java_root>";
/*package*/ static final DeclarationDescriptor JAVA_METHOD_TYPE_PARAMETER_PARENT = new DeclarationDescriptorImpl(null, Collections.<AnnotationDescriptor>emptyList(), "<java_generic_method>") {
@@ -186,8 +187,8 @@ public class JavaDescriptorResolver {
}
}
protected final Map<String, ResolverBinaryClassData> classDescriptorCache = Maps.newHashMap();
protected final Map<String, ResolverNamespaceData> namespaceDescriptorCacheByFqn = Maps.newHashMap();
protected final Map<FqName, ResolverBinaryClassData> classDescriptorCache = Maps.newHashMap();
protected final Map<FqName, ResolverNamespaceData> namespaceDescriptorCacheByFqn = Maps.newHashMap();
protected final Map<PsiElement, ResolverNamespaceData> namespaceDescriptorCache = Maps.newHashMap();
protected final JavaPsiFacade javaFacade;
@@ -209,9 +210,9 @@ public class JavaDescriptorResolver {
@Nullable
ResolverClassData resolveClassData(@NotNull PsiClass psiClass) {
String qualifiedName = psiClass.getQualifiedName();
FqName qualifiedName = new FqName(psiClass.getQualifiedName());
if (qualifiedName.endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) {
if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) {
// TODO: only if -$$TImpl class is created by Kotlin
return null;
}
@@ -249,9 +250,9 @@ public class JavaDescriptorResolver {
}
@Nullable
public ClassDescriptor resolveClass(@NotNull String qualifiedName) {
public ClassDescriptor resolveClass(@NotNull FqName qualifiedName) {
if (qualifiedName.endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) {
if (qualifiedName.getFqName().endsWith(JvmAbi.TRAIT_IMPL_SUFFIX)) {
// TODO: only if -$$TImpl class is created by Kotlin
return null;
}
@@ -276,7 +277,7 @@ public class JavaDescriptorResolver {
}
private ResolverBinaryClassData createJavaClassDescriptor(@NotNull final PsiClass psiClass) {
if (classDescriptorCache.containsKey(psiClass.getQualifiedName())) {
if (classDescriptorCache.containsKey(new FqName(psiClass.getQualifiedName()))) {
throw new IllegalStateException(psiClass.getQualifiedName());
}
@@ -284,7 +285,7 @@ public class JavaDescriptorResolver {
String name = psiClass.getName();
ResolverBinaryClassData classData = new ResolverBinaryClassData();
classDescriptorCache.put(psiClass.getQualifiedName(), classData);
classDescriptorCache.put(new FqName(psiClass.getQualifiedName()), classData);
ClassKind kind = psiClass.isInterface() ? (psiClass.isAnnotationType() ? ClassKind.ANNOTATION_CLASS : ClassKind.TRAIT) : ClassKind.CLASS;
ClassOrNamespaceDescriptor containingDeclaration = resolveParentDescriptor(psiClass);
classData.classDescriptor = new MutableClassDescriptorLite(containingDeclaration, kind);
@@ -459,7 +460,7 @@ public class JavaDescriptorResolver {
classData.kotlin = true;
classData.classDescriptor = new MutableClassDescriptorLite(containing, ClassKind.OBJECT);
classDescriptorCache.put(classObjectPsiClass.getQualifiedName(), classData);
classDescriptorCache.put(new FqName(classObjectPsiClass.getQualifiedName()), classData);
classData.classDescriptor.setSupertypes(getSupertypes(new PsiClassWrapper(classObjectPsiClass), classData.classDescriptor, new ArrayList<TypeParameterDescriptor>(0)));
classData.classDescriptor.setName(JetPsiUtil.NO_NAME_PROVIDED); // TODO
@@ -506,7 +507,7 @@ public class JavaDescriptorResolver {
@NotNull
private ClassDescriptor getJavaLangObject() {
if (javaLangObject == null) {
javaLangObject = resolveClass("java.lang.Object");
javaLangObject = resolveClass(new FqName("java.lang.Object"));
}
return javaLangObject;
}
@@ -653,16 +654,7 @@ public class JavaDescriptorResolver {
return resolveClass(containingClass);
}
return resolveNamespace(packageNameOfClass(psiClass.getQualifiedName()));
}
private static String packageNameOfClass(@NotNull String qualifiedName) {
int lastDot = qualifiedName.lastIndexOf('.');
if (lastDot < 0) {
return "";
} else {
return qualifiedName.substring(0, lastDot);
}
return resolveNamespace(new FqName(psiClass.getQualifiedName()).parent());
}
private List<TypeParameterDescriptorInitialization> makeUninitializedTypeParameters(@NotNull DeclarationDescriptor containingDeclaration, @NotNull PsiTypeParameter[] typeParameters) {
@@ -792,7 +784,7 @@ public class JavaDescriptorResolver {
}
@Nullable
public NamespaceDescriptor resolveNamespace(@NotNull String qualifiedName) {
public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName) {
// First, let's check that there is no Kotlin package:
NamespaceDescriptor kotlinNamespaceDescriptor = semanticServices.getKotlinNamespaceDescriptor(qualifiedName);
if (kotlinNamespaceDescriptor != null) {
@@ -809,8 +801,8 @@ public class JavaDescriptorResolver {
}
@Nullable
public PsiClass findClass(@NotNull String qualifiedName) {
PsiClass original = javaFacade.findClass(qualifiedName, javaSearchScope);
public PsiClass findClass(@NotNull FqName qualifiedName) {
PsiClass original = javaFacade.findClass(qualifiedName.getFqName(), javaSearchScope);
PsiClass altClass = altClassFinder.findClass(qualifiedName);
PsiClass result = original;
if (altClass != null) {
@@ -822,7 +814,7 @@ public class JavaDescriptorResolver {
}
if (result != null) {
String actualQualifiedName = result.getQualifiedName();
FqName actualQualifiedName = new FqName(result.getQualifiedName());
if (!actualQualifiedName.equals(qualifiedName)) {
// throw new IllegalStateException("requested " + qualifiedName + ", got " + actualQualifiedName);
}
@@ -831,8 +823,8 @@ public class JavaDescriptorResolver {
return result;
}
/*package*/ PsiPackage findPackage(String qualifiedName) {
return javaFacade.findPackage(qualifiedName);
/*package*/ PsiPackage findPackage(@NotNull FqName qualifiedName) {
return javaFacade.findPackage(qualifiedName.getFqName());
}
private NamespaceDescriptor resolveNamespace(@NotNull PsiPackage psiPackage) {
@@ -840,7 +832,7 @@ public class JavaDescriptorResolver {
if (namespaceData == null) {
namespaceData = createJavaNamespaceDescriptor(psiPackage);
namespaceDescriptorCache.put(psiPackage, namespaceData);
namespaceDescriptorCacheByFqn.put(psiPackage.getQualifiedName(), namespaceData);
namespaceDescriptorCacheByFqn.put(new FqName(psiPackage.getQualifiedName()), namespaceData);
}
return namespaceData.namespaceDescriptor;
}
@@ -850,7 +842,7 @@ public class JavaDescriptorResolver {
if (namespaceData == null) {
namespaceData = createJavaNamespaceDescriptor(psiClass);
namespaceDescriptorCache.put(psiClass, namespaceData);
namespaceDescriptorCacheByFqn.put(psiClass.getQualifiedName(), namespaceData);
namespaceDescriptorCacheByFqn.put(new FqName(psiClass.getQualifiedName()), namespaceData);
}
return namespaceData.namespaceDescriptor;
}
@@ -862,11 +854,11 @@ public class JavaDescriptorResolver {
resolveParentDescriptor(psiPackage),
Collections.<AnnotationDescriptor>emptyList(), // TODO
name == null ? JAVA_ROOT : name,
name == null ? JAVA_ROOT : psiPackage.getQualifiedName(),
name == null ? FqName.ROOT : new FqName(psiPackage.getQualifiedName()),
true
);
namespaceData.namespaceDescriptor.setMemberScope(new JavaPackageScope(psiPackage.getQualifiedName(), namespaceData.namespaceDescriptor, semanticServices));
namespaceData.namespaceDescriptor.setMemberScope(new JavaPackageScope(new FqName(psiPackage.getQualifiedName()), namespaceData.namespaceDescriptor, semanticServices));
semanticServices.getTrace().record(BindingContext.NAMESPACE, psiPackage, namespaceData.namespaceDescriptor);
// TODO: hack
namespaceData.kotlin = true;
@@ -894,7 +886,7 @@ public class JavaDescriptorResolver {
resolveParentDescriptor(psiClass),
Collections.<AnnotationDescriptor>emptyList(), // TODO
psiClass.getName(),
psiClass.getQualifiedName(),
new FqName(psiClass.getQualifiedName()),
false
);
namespaceData.namespaceDescriptor.setMemberScope(new JavaClassMembersScope(namespaceData.namespaceDescriptor, psiClass, semanticServices, true));
@@ -1340,7 +1332,7 @@ public class JavaDescriptorResolver {
scopeData = namespaceDescriptorCacheByFqn.get(((JavaNamespaceDescriptor) owner).getQualifiedName());
staticMembers = true;
} else if (owner instanceof ClassDescriptor) {
scopeData = classDescriptorCache.get(psiClass.getQualifiedName());
scopeData = classDescriptorCache.get(new FqName(psiClass.getQualifiedName()));
staticMembers = false;
} else {
throw new IllegalStateException("unknown owner: " + owner.getClass().getName());
@@ -1428,7 +1420,7 @@ public class JavaDescriptorResolver {
}
kotlin = namespaceData.kotlin;
} else {
ResolverBinaryClassData classData = classDescriptorCache.get(psiClass.getQualifiedName());
ResolverBinaryClassData classData = classDescriptorCache.get(new FqName(psiClass.getQualifiedName()));
if (classData == null) {
throw new IllegalStateException("classData not found by name " + psiClass.getQualifiedName());
}
@@ -1516,7 +1508,7 @@ public class JavaDescriptorResolver {
return null;
}
ClassDescriptor clazz = resolveClass(psiAnnotation.getQualifiedName());
ClassDescriptor clazz = resolveClass(new FqName(psiAnnotation.getQualifiedName()));
if (clazz == null) {
return null;
}
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.AbstractNamespaceDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.FqName;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import java.util.List;
@@ -29,12 +30,12 @@ import java.util.List;
*/
public class JavaNamespaceDescriptor extends AbstractNamespaceDescriptorImpl {
private JetScope memberScope;
private final String qualifiedName;
private final FqName qualifiedName;
/** Namespace of class with static methods */
private final boolean namespace;
public JavaNamespaceDescriptor(DeclarationDescriptor containingDeclaration, List<AnnotationDescriptor> annotations,
@NotNull String name, @NotNull String qualifiedName, boolean namespace) {
@NotNull String name, @NotNull FqName qualifiedName, boolean namespace) {
super(containingDeclaration, annotations, name);
this.qualifiedName = qualifiedName;
this.namespace = namespace;
@@ -50,7 +51,7 @@ public class JavaNamespaceDescriptor extends AbstractNamespaceDescriptorImpl {
return memberScope;
}
public String getQualifiedName() {
public FqName getQualifiedName() {
return qualifiedName;
}
@@ -18,21 +18,18 @@ package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Sets;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.FqName;
import java.util.Collection;
import java.util.HashSet;
/**
* @author abreslav
@@ -42,19 +39,19 @@ public class JavaPackageScope extends JavaClassOrPackageScope {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.migration.PsiMigrationImpl");
@NotNull
private final String packageFQN;
private final FqName packageFQN;
private Collection<DeclarationDescriptor> allDescriptors;
public JavaPackageScope(
@NotNull String packageFQN,
@NotNull FqName packageFQN,
@NotNull NamespaceDescriptor containingDescriptor,
@NotNull JavaSemanticServices semanticServices) {
super(containingDescriptor, semanticServices, getPiClass(packageFQN, semanticServices));
this.packageFQN = packageFQN;
}
private static PsiClass getPiClass(String packageFQN, JavaSemanticServices semanticServices) {
private static PsiClass getPiClass(FqName packageFQN, JavaSemanticServices semanticServices) {
// TODO: move this check outside
// If this package is actually a Kotlin namespace, then we access it through a namespace descriptor, and
// Kotlin functions are already there
@@ -63,7 +60,7 @@ public class JavaPackageScope extends JavaClassOrPackageScope {
return null;
} else {
// TODO: what is GlobalSearchScope
return semanticServices.getDescriptorResolver().javaFacade.findClass(getQualifiedName(packageFQN, JvmAbi.PACKAGE_CLASS));
return semanticServices.getDescriptorResolver().javaFacade.findClass(getQualifiedName(packageFQN, JvmAbi.PACKAGE_CLASS).getFqName());
}
}
@@ -113,12 +110,12 @@ public class JavaPackageScope extends JavaClassOrPackageScope {
final PsiPackage javaPackage = semanticServices.getDescriptorResolver().findPackage(packageFQN);
if (javaPackage != null) {
boolean isKotlinNamespace = semanticServices.getKotlinNamespaceDescriptor(javaPackage.getQualifiedName()) != null;
boolean isKotlinNamespace = semanticServices.getKotlinNamespaceDescriptor(new FqName(javaPackage.getQualifiedName())) != null;
final JavaDescriptorResolver descriptorResolver = semanticServices.getDescriptorResolver();
for (PsiPackage psiSubPackage : javaPackage.getSubPackages()) {
if (semanticServices.getKotlinNamespaceDescriptor(psiSubPackage.getQualifiedName()) == null) {
allDescriptors.add(descriptorResolver.resolveNamespace(psiSubPackage.getQualifiedName()));
if (semanticServices.getKotlinNamespaceDescriptor(new FqName(psiSubPackage.getQualifiedName())) == null) {
allDescriptors.add(descriptorResolver.resolveNamespace(new FqName(psiSubPackage.getQualifiedName())));
}
}
@@ -128,7 +125,7 @@ public class JavaPackageScope extends JavaClassOrPackageScope {
}
// If this is a Kotlin class, we have already taken it through a containing namespace descriptor
ClassDescriptor kotlinClassDescriptor = semanticServices.getKotlinClassDescriptor(psiClass.getQualifiedName());
ClassDescriptor kotlinClassDescriptor = semanticServices.getKotlinClassDescriptor(new FqName(psiClass.getQualifiedName()));
if (kotlinClassDescriptor != null) {
continue;
}
@@ -151,7 +148,8 @@ public class JavaPackageScope extends JavaClassOrPackageScope {
return allDescriptors;
}
private static String getQualifiedName(@NotNull String packageFQN, @NotNull String name) {
return (packageFQN.isEmpty() ? "" : packageFQN + ".") + name;
@NotNull
private static FqName getQualifiedName(@NotNull FqName packageFQN, @NotNull String name) {
return packageFQN.child(name);
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingTrace;
import org.jetbrains.jet.lang.resolve.FqName;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
/**
@@ -55,9 +56,9 @@ public class JavaSemanticServices {
}
@Nullable
public ClassDescriptor getKotlinClassDescriptor(String qualifiedName) {
if (qualifiedName.startsWith("jet.")) {
ClassDescriptor r = (ClassDescriptor) JetStandardLibrary.getInstance().getLibraryScope().getClassifier(qualifiedName.substring("jet.".length()));
public ClassDescriptor getKotlinClassDescriptor(@NotNull FqName qualifiedName) {
if (qualifiedName.getFqName().startsWith("jet.")) {
ClassDescriptor r = (ClassDescriptor) JetStandardLibrary.getInstance().getLibraryScope().getClassifier(qualifiedName.getFqName().substring("jet.".length()));
if (r == null) {
// TODO: better error
//throw new IllegalStateException();
@@ -68,7 +69,7 @@ public class JavaSemanticServices {
}
@Nullable
public NamespaceDescriptor getKotlinNamespaceDescriptor(String qualifiedName) {
public NamespaceDescriptor getKotlinNamespaceDescriptor(@NotNull FqName qualifiedName) {
return getTrace().get(BindingContext.FQNAME_TO_NAMESPACE_DESCRIPTOR, qualifiedName);
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.java;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.resolve.FqName;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
@@ -85,30 +86,30 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
@Override
public void visitClassType(String name, boolean nullable, boolean forceReal) {
String ourName = name
FqName ourName = new FqName(name
.replace('/', '.')
.replace('$', '.') // TODO: not sure
;
);
this.classDescriptor = null;
if (this.classDescriptor == null && !forceReal) {
this.classDescriptor = this.javaSemanticServices.getTypeTransformer().getPrimitiveWrappersClassDescriptorMap().get(ourName);
this.classDescriptor = this.javaSemanticServices.getTypeTransformer().getPrimitiveWrappersClassDescriptorMap().get(ourName.getFqName());
}
if (this.classDescriptor == null && ourName.equals("java.lang.Object") && !forceReal) {
if (this.classDescriptor == null && ourName.equals(new FqName("java.lang.Object")) && !forceReal) {
this.classDescriptor = JetStandardClasses.getAny();
}
if (classDescriptor == null) {
// TODO: this is the worst code in Kotlin project
Matcher matcher = Pattern.compile("jet\\.Function(\\d+)").matcher(ourName);
Matcher matcher = Pattern.compile("jet\\.Function(\\d+)").matcher(ourName.getFqName());
if (matcher.matches()) {
classDescriptor = JetStandardClasses.getFunction(Integer.parseInt(matcher.group(1)));
}
}
if (classDescriptor == null) {
Matcher matcher = Pattern.compile("jet\\.Tuple(\\d+)").matcher(ourName);
Matcher matcher = Pattern.compile("jet\\.Tuple(\\d+)").matcher(ourName.getFqName());
if (matcher.matches()) {
classDescriptor = JetStandardClasses.getTuple(Integer.parseInt(matcher.group(1)));
}
@@ -25,6 +25,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.resolve.FqName;
import org.jetbrains.jet.plugin.compiler.PathUtil;
import java.util.List;
@@ -39,9 +40,9 @@ public class AltClassFinder {
this.roots = PathUtil.getAltHeadersRoots();
}
public PsiClass findClass(@NotNull String qualifiedName) {
public PsiClass findClass(@NotNull FqName qualifiedName) {
for (final VirtualFile classRoot : roots) {
PsiClass answer = CoreJavaFileManager.findClassInClasspathRoot(qualifiedName, classRoot, psiManager);
PsiClass answer = CoreJavaFileManager.findClassInClasspathRoot(qualifiedName.getFqName(), classRoot, psiManager);
if (answer != null) return answer;
}