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