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 NamespaceDescriptor getNamespace(@NotNull Name name) {
062 for (JetScope jetScope : scopeChain) {
063 NamespaceDescriptor namespace = jetScope.getNamespace(name);
064 if (namespace != null) {
065 return namespace;
066 }
067 }
068 return null;
069 }
070
071 @NotNull
072 @Override
073 public Set<VariableDescriptor> getProperties(@NotNull Name name) {
074 Set<VariableDescriptor> properties = Sets.newLinkedHashSet();
075 for (JetScope jetScope : scopeChain) {
076 properties.addAll(jetScope.getProperties(name));
077 }
078 return properties;
079 }
080
081 @Override
082 public VariableDescriptor getLocalVariable(@NotNull Name name) {
083 for (JetScope jetScope : scopeChain) {
084 VariableDescriptor variable = jetScope.getLocalVariable(name);
085 if (variable != null) {
086 return variable;
087 }
088 }
089 return null;
090 }
091
092 @NotNull
093 @Override
094 public Set<FunctionDescriptor> getFunctions(@NotNull Name name) {
095 if (scopeChain.length == 0) {
096 return Collections.emptySet();
097 }
098
099 Set<FunctionDescriptor> result = Sets.newLinkedHashSet();
100 for (JetScope jetScope : scopeChain) {
101 result.addAll(jetScope.getFunctions(name));
102 }
103 return result;
104 }
105
106 @NotNull
107 @Override
108 public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() {
109 if (implicitReceiverHierarchy == null) {
110 implicitReceiverHierarchy = Lists.newArrayList();
111 for (JetScope jetScope : scopeChain) {
112 implicitReceiverHierarchy.addAll(jetScope.getImplicitReceiversHierarchy());
113 }
114 }
115 return implicitReceiverHierarchy;
116 }
117
118 @NotNull
119 @Override
120 public DeclarationDescriptor getContainingDeclaration() {
121 return containingDeclaration;
122 }
123
124 @NotNull
125 @Override
126 public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) {
127 for (JetScope jetScope : scopeChain) {
128 Collection<DeclarationDescriptor> declarationsByLabel = jetScope.getDeclarationsByLabel(labelName);
129 if (!declarationsByLabel.isEmpty()) return declarationsByLabel; // TODO : merge?
130 }
131 return Collections.emptyList();
132 }
133
134 @NotNull
135 @Override
136 public Collection<DeclarationDescriptor> getAllDescriptors() {
137 if (allDescriptors == null) {
138 allDescriptors = Sets.newHashSet();
139 for (JetScope scope : scopeChain) {
140 allDescriptors.addAll(scope.getAllDescriptors());
141 }
142 }
143 return allDescriptors;
144 }
145
146 @NotNull
147 @Override
148 public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
149 throw new UnsupportedOperationException();
150 }
151
152 @Override
153 public String toString() {
154 return debugName;
155 }
156
157 @TestOnly
158 @Override
159 public void printScopeStructure(@NotNull Printer p) {
160 p.println(getClass().getSimpleName(), ": ", debugName, " {");
161 p.pushIndent();
162
163 for (JetScope scope : scopeChain) {
164 scope.printScopeStructure(p);
165 }
166
167 p.popIndent();
168 p.println("}");
169 }
170 }