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    }