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    }