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