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.scopes;
018    
019    import com.google.common.collect.Lists;
020    import com.google.common.collect.Sets;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.TestOnly;
023    import org.jetbrains.jet.lang.descriptors.*;
024    import org.jetbrains.jet.lang.resolve.name.Name;
025    import org.jetbrains.jet.utils.Printer;
026    
027    import java.util.*;
028    
029    import static org.jetbrains.jet.lang.resolve.scopes.JetScopeSelectorUtil.*;
030    
031    public class ChainedScope implements JetScope {
032        private final DeclarationDescriptor containingDeclaration;
033        private final String debugName;
034        private final JetScope[] scopeChain;
035        private Collection<DeclarationDescriptor> allDescriptors;
036        private List<ReceiverParameterDescriptor> implicitReceiverHierarchy;
037    
038        public ChainedScope(DeclarationDescriptor containingDeclaration, String debugName, JetScope... scopes) {
039            this.containingDeclaration = containingDeclaration;
040            scopeChain = scopes.clone();
041    
042            this.debugName = debugName;
043        }
044    
045        @Override
046        public ClassifierDescriptor getClassifier(@NotNull Name name) {
047            return getFirstMatch(scopeChain, name, CLASSIFIER_DESCRIPTOR_SCOPE_SELECTOR);
048        }
049    
050        @Override
051        public PackageViewDescriptor getPackage(@NotNull Name name) {
052            return getFirstMatch(scopeChain, name, PACKAGE_SCOPE_SELECTOR);
053        }
054    
055        @NotNull
056        @Override
057        public Set<VariableDescriptor> getProperties(@NotNull Name name) {
058            return getFromAllScopes(scopeChain, name, NAMED_PROPERTIES_SCOPE_SELECTOR);
059        }
060    
061        @Override
062        public VariableDescriptor getLocalVariable(@NotNull Name name) {
063            return getFirstMatch(scopeChain, name, VARIABLE_DESCRIPTOR_SCOPE_SELECTOR);
064        }
065    
066        @NotNull
067        @Override
068        public Set<FunctionDescriptor> getFunctions(@NotNull Name name) {
069            return getFromAllScopes(scopeChain, name, NAMED_FUNCTION_SCOPE_SELECTOR);
070        }
071    
072        @NotNull
073        @Override
074        public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
075            if (implicitReceiverHierarchy == null) {
076                implicitReceiverHierarchy = Lists.newArrayList();
077                for (JetScope jetScope : scopeChain) {
078                    implicitReceiverHierarchy.addAll(jetScope.getImplicitReceiversHierarchy());
079                }
080            }
081            return implicitReceiverHierarchy;
082        }
083    
084        @NotNull
085        @Override
086        public DeclarationDescriptor getContainingDeclaration() {
087            return containingDeclaration;
088        }
089    
090        @NotNull
091        @Override
092        public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull Name labelName) {
093            ArrayList<DeclarationDescriptor> result = new ArrayList<DeclarationDescriptor>();
094            for (JetScope jetScope : scopeChain) {
095                result.addAll(jetScope.getDeclarationsByLabel(labelName));
096            }
097            result.trimToSize();
098            return result;
099        }
100    
101        @NotNull
102        @Override
103        public Collection<DeclarationDescriptor> getAllDescriptors() {
104            if (allDescriptors == null) {
105                allDescriptors = Sets.newHashSet();
106                for (JetScope scope : scopeChain) {
107                    allDescriptors.addAll(scope.getAllDescriptors());
108                }
109            }
110            return allDescriptors;
111        }
112    
113        @NotNull
114        @Override
115        public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
116            throw new UnsupportedOperationException();
117        }
118    
119        @Override
120        public String toString() {
121            return debugName;
122        }
123    
124        @TestOnly
125        @Override
126        public void printScopeStructure(@NotNull Printer p) {
127            p.println(getClass().getSimpleName(), ": ", debugName, " {");
128            p.pushIndent();
129    
130            for (JetScope scope : scopeChain) {
131                scope.printScopeStructure(p);
132            }
133    
134            p.popIndent();
135            p.println("}");
136        }
137    }