001    /*
002     * Copyright 2010-2013 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.jet.lang.resolve.lazy.descriptors;
018    
019    import com.intellij.util.Function;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.jet.lang.descriptors.*;
023    import org.jetbrains.jet.lang.psi.JetDeclaration;
024    import org.jetbrains.jet.lang.psi.JetFile;
025    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
026    import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
027    import org.jetbrains.jet.lang.resolve.lazy.declarations.PackageMemberDeclarationProvider;
028    import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNullable;
029    import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
030    import org.jetbrains.jet.lang.resolve.name.FqName;
031    import org.jetbrains.jet.lang.resolve.name.Name;
032    import org.jetbrains.jet.lang.resolve.scopes.JetScope;
033    
034    import java.util.Collection;
035    import java.util.Set;
036    
037    public class LazyPackageMemberScope extends AbstractLazyMemberScope<NamespaceDescriptor, PackageMemberDeclarationProvider> {
038    
039        private final MemoizedFunctionToNullable<Name, NamespaceDescriptor> packageDescriptors;
040    
041        public LazyPackageMemberScope(@NotNull ResolveSession resolveSession,
042                @NotNull PackageMemberDeclarationProvider declarationProvider,
043                @NotNull NamespaceDescriptor thisPackage) {
044            super(resolveSession, declarationProvider, thisPackage);
045    
046            this.packageDescriptors = resolveSession.getStorageManager().createMemoizedFunctionWithNullableValues(
047                    new Function<Name, NamespaceDescriptor>() {
048                        @Override
049                        public NamespaceDescriptor fun(Name name) {
050                            return createPackageDescriptor(name);
051                        }
052                    }, StorageManager.ReferenceKind.STRONG);
053        }
054    
055        @Override
056        public NamespaceDescriptor getNamespace(@NotNull Name name) {
057            return packageDescriptors.fun(name);
058        }
059    
060        @Nullable
061        public NamespaceDescriptor createPackageDescriptor(@NotNull Name name) {
062            if (!declarationProvider.isPackageDeclared(name)) return null;
063    
064            PackageMemberDeclarationProvider packageMemberDeclarationProvider = resolveSession.getDeclarationProviderFactory().getPackageMemberDeclarationProvider(
065                    DescriptorUtils.getFQName(thisDescriptor).child(name).toSafe());
066            assert packageMemberDeclarationProvider != null : "Package is declared, but declaration provider is not found: " + name;
067    
068            return new LazyPackageDescriptor(thisDescriptor, name, resolveSession, packageMemberDeclarationProvider);
069        }
070    
071        @Override
072        public ClassifierDescriptor getClassifier(@NotNull Name name) {
073            // TODO: creating an FqName every time may be a performance problem
074            Name actualName = resolveSession.resolveClassifierAlias(DescriptorUtils.getFQName(thisDescriptor).toSafe(), name);
075            return super.getClassifier(actualName);
076        }
077    
078        @NotNull
079        @Override
080        protected JetScope getScopeForMemberDeclarationResolution(JetDeclaration declaration) {
081            return resolveSession.getInjector().getScopeProvider().getFileScope((JetFile) declaration.getContainingFile());
082        }
083    
084        @Override
085        protected ReceiverParameterDescriptor getImplicitReceiver() {
086            return ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
087        }
088    
089        @Override
090        protected void getNonDeclaredFunctions(@NotNull Name name, @NotNull Set<FunctionDescriptor> result) {
091            // No extra functions
092        }
093    
094        @Override
095        protected void getNonDeclaredProperties(@NotNull Name name, @NotNull Set<VariableDescriptor> result) {
096            // No extra properties
097        }
098    
099        @Override
100        protected void addExtraDescriptors(@NotNull Collection<DeclarationDescriptor> result) {
101            for (FqName packageFqName : declarationProvider.getAllDeclaredPackages()) {
102                result.add(getNamespace(packageFqName.shortName()));
103            }
104        }
105    
106        @Override
107        public String toString() {
108            // Do not add details here, they may compromise the laziness during debugging
109            return "lazy scope for package " + thisDescriptor.getName();
110        }
111    }