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
017package org.jetbrains.jet.lang.resolve.lazy.descriptors;
018
019import com.intellij.util.Function;
020import org.jetbrains.annotations.NotNull;
021import org.jetbrains.annotations.Nullable;
022import org.jetbrains.jet.lang.descriptors.*;
023import org.jetbrains.jet.lang.psi.JetDeclaration;
024import org.jetbrains.jet.lang.psi.JetFile;
025import org.jetbrains.jet.lang.resolve.DescriptorUtils;
026import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
027import org.jetbrains.jet.lang.resolve.lazy.declarations.PackageMemberDeclarationProvider;
028import org.jetbrains.jet.lang.resolve.lazy.storage.MemoizedFunctionToNullable;
029import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
030import org.jetbrains.jet.lang.resolve.name.FqName;
031import org.jetbrains.jet.lang.resolve.name.Name;
032import org.jetbrains.jet.lang.resolve.scopes.JetScope;
033
034import java.util.Collection;
035import java.util.Set;
036
037public 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}