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