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 public class ChainedScope implements JetScope {
034 private final DeclarationDescriptor containingDeclaration;
035 private final String debugName;
036 private final JetScope[] scopeChain;
037 private Collection<DeclarationDescriptor> allDescriptors;
038 private List<ReceiverParameterDescriptor> implicitReceiverHierarchy;
039
040 public ChainedScope(DeclarationDescriptor containingDeclaration, JetScope... scopes) {
041 this(containingDeclaration, "Untitled chained scope", scopes);
042 }
043
044 public ChainedScope(DeclarationDescriptor containingDeclaration, String debugName, JetScope... scopes) {
045 this.containingDeclaration = containingDeclaration;
046 scopeChain = scopes.clone();
047
048 this.debugName = debugName;
049 }
050
051 @Override
052 public ClassifierDescriptor getClassifier(@NotNull Name name) {
053 for (JetScope scope : scopeChain) {
054 ClassifierDescriptor classifier = scope.getClassifier(name);
055 if (classifier != null) return classifier;
056 }
057 return null;
058 }
059
060 @Override
061 public ClassDescriptor getObjectDescriptor(@NotNull Name name) {
062 for (JetScope scope : scopeChain) {
063 ClassDescriptor objectDescriptor = scope.getObjectDescriptor(name);
064 if (objectDescriptor != null) return objectDescriptor;
065 }
066 return null;
067 }
068
069 @NotNull
070 @Override
071 public Set<ClassDescriptor> getObjectDescriptors() {
072 Set<ClassDescriptor> objectDescriptors = Sets.newHashSet();
073 for (JetScope scope : scopeChain) {
074 objectDescriptors.addAll(scope.getObjectDescriptors());
075 }
076 return objectDescriptors;
077 }
078
079 @Override
080 public NamespaceDescriptor getNamespace(@NotNull Name name) {
081 for (JetScope jetScope : scopeChain) {
082 NamespaceDescriptor namespace = jetScope.getNamespace(name);
083 if (namespace != null) {
084 return namespace;
085 }
086 }
087 return null;
088 }
089
090 @NotNull
091 @Override
092 public Set<VariableDescriptor> getProperties(@NotNull Name name) {
093 Set<VariableDescriptor> properties = Sets.newLinkedHashSet();
094 for (JetScope jetScope : scopeChain) {
095 properties.addAll(jetScope.getProperties(name));
096 }
097 return properties;
098 }
099
100 @Override
101 public VariableDescriptor getLocalVariable(@NotNull Name name) {
102 for (JetScope jetScope : scopeChain) {
103 VariableDescriptor variable = jetScope.getLocalVariable(name);
104 if (variable != null) {
105 return variable;
106 }
107 }
108 return null;
109 }
110
111 @NotNull
112 @Override
113 public Set<FunctionDescriptor> getFunctions(@NotNull Name name) {
114 if (scopeChain.length == 0) {
115 return Collections.emptySet();
116 }
117
118 Set<FunctionDescriptor> result = Sets.newLinkedHashSet();
119 for (JetScope jetScope : scopeChain) {
120 result.addAll(jetScope.getFunctions(name));
121 }
122 return result;
123 }
124
125 @NotNull
126 @Override
127 public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
128 if (implicitReceiverHierarchy == null) {
129 implicitReceiverHierarchy = Lists.newArrayList();
130 for (JetScope jetScope : scopeChain) {
131 implicitReceiverHierarchy.addAll(jetScope.getImplicitReceiversHierarchy());
132 }
133 }
134 return implicitReceiverHierarchy;
135 }
136
137 @NotNull
138 @Override
139 public DeclarationDescriptor getContainingDeclaration() {
140 return containingDeclaration;
141 }
142
143 @NotNull
144 @Override
145 public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) {
146 for (JetScope jetScope : scopeChain) {
147 Collection<DeclarationDescriptor> declarationsByLabel = jetScope.getDeclarationsByLabel(labelName);
148 if (!declarationsByLabel.isEmpty()) return declarationsByLabel; // TODO : merge?
149 }
150 return Collections.emptyList();
151 }
152
153 @NotNull
154 @Override
155 public Collection<DeclarationDescriptor> getAllDescriptors() {
156 if (allDescriptors == null) {
157 allDescriptors = Sets.newHashSet();
158 for (JetScope scope : scopeChain) {
159 allDescriptors.addAll(scope.getAllDescriptors());
160 }
161 }
162 return allDescriptors;
163 }
164
165 @NotNull
166 @Override
167 public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
168 throw new UnsupportedOperationException();
169 }
170
171 @Override
172 public String toString() {
173 return debugName;
174 }
175
176 @TestOnly
177 @Override
178 public void printScopeStructure(@NotNull Printer p) {
179 p.println(getClass().getSimpleName(), ": ", debugName, " {");
180 p.pushIndent();
181
182 for (JetScope scope : scopeChain) {
183 scope.printScopeStructure(p);
184 }
185
186 p.popIndent();
187 p.println("}");
188 }
189 }