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