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