001 /*
002 * Copyright 2010-2015 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.kotlin.resolve.lazy;
018
019 import com.google.common.base.Predicate;
020 import com.google.common.base.Predicates;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.kotlin.descriptors.ClassDescriptor;
024 import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
025 import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
026 import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
027 import org.jetbrains.kotlin.name.FqName;
028 import org.jetbrains.kotlin.name.Name;
029 import org.jetbrains.kotlin.name.NamePackage;
030 import org.jetbrains.kotlin.name.SpecialNames;
031 import org.jetbrains.kotlin.psi.JetNamedDeclaration;
032 import org.jetbrains.kotlin.psi.JetNamedDeclarationUtil;
033 import org.jetbrains.kotlin.resolve.scopes.JetScope;
034
035 import java.util.ArrayList;
036 import java.util.Collection;
037 import java.util.Collections;
038
039 public class ResolveSessionUtils {
040
041 private ResolveSessionUtils() {
042 }
043
044 @NotNull
045 public static Collection<ClassDescriptor> getClassDescriptorsByFqName(@NotNull ModuleDescriptor module, @NotNull FqName fqName) {
046 return getClassOrObjectDescriptorsByFqName(module, fqName, Predicates.<ClassDescriptor>alwaysTrue());
047 }
048
049 @NotNull
050 public static Collection<ClassDescriptor> getClassOrObjectDescriptorsByFqName(
051 @NotNull ModuleDescriptor module,
052 @NotNull FqName fqName,
053 @NotNull Predicate<ClassDescriptor> filter
054 ) {
055 if (fqName.isRoot()) return Collections.emptyList();
056
057 Collection<ClassDescriptor> result = new ArrayList<ClassDescriptor>(1);
058
059 FqName packageFqName = fqName.parent();
060 while (true) {
061 PackageViewDescriptor packageDescriptor = module.getPackage(packageFqName);
062 if (packageDescriptor != null) {
063 FqName relativeClassFqName = NamePackage.tail(fqName, packageFqName);
064 ClassDescriptor classDescriptor = findByQualifiedName(packageDescriptor.getMemberScope(), relativeClassFqName);
065 if (classDescriptor != null && filter.apply(classDescriptor)) {
066 result.add(classDescriptor);
067 }
068 }
069
070 if (packageFqName.isRoot()) {
071 break;
072 }
073
074 packageFqName = packageFqName.parent();
075 }
076
077 return result;
078 }
079
080 @Nullable
081 public static ClassDescriptor findByQualifiedName(@NotNull JetScope outerScope, @NotNull FqName path) {
082 if (path.isRoot()) return null;
083
084 JetScope scope = outerScope;
085 for (Name name : path.pathSegments()) {
086 ClassifierDescriptor classifier = scope.getClassifier(name);
087 if (!(classifier instanceof ClassDescriptor)) return null;
088 scope = ((ClassDescriptor) classifier).getUnsubstitutedInnerClassesScope();
089 }
090
091 return (ClassDescriptor) scope.getContainingDeclaration();
092 }
093
094 @NotNull
095 public static Name safeNameForLazyResolve(@NotNull JetNamedDeclaration declaration) {
096 return safeNameForLazyResolve(declaration.getNameAsName());
097 }
098
099 @NotNull
100 public static Name safeNameForLazyResolve(@Nullable Name name) {
101 return SpecialNames.safeIdentifier(name);
102 }
103
104 @Nullable
105 public static FqName safeFqNameForLazyResolve(@NotNull JetNamedDeclaration declaration) {
106 //NOTE: should only create special names for package level declarations, so we can safely rely on real fq name for parent
107 FqName parentFqName = JetNamedDeclarationUtil.getParentFqName(declaration);
108 return parentFqName != null ? parentFqName.child(safeNameForLazyResolve(declaration)) : null;
109 }
110 }