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.Multimap;
021 import com.google.common.collect.Sets;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.annotations.TestOnly;
025 import org.jetbrains.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.resolve.name.LabelName;
027 import org.jetbrains.jet.lang.resolve.name.Name;
028 import org.jetbrains.jet.utils.Printer;
029
030 import java.util.Collection;
031 import java.util.Set;
032
033 public class WriteThroughScope extends WritableScopeWithImports {
034 private final WritableScope writableWorker;
035 private Collection<DeclarationDescriptor> allDescriptors;
036
037 public WriteThroughScope(@NotNull JetScope outerScope, @NotNull WritableScope scope,
038 @NotNull RedeclarationHandler redeclarationHandler, @NotNull String debugName) {
039 super(outerScope, redeclarationHandler, debugName);
040 this.writableWorker = scope;
041 }
042
043 @Override
044 @NotNull
045 public Collection<DeclarationDescriptor> getDeclarationsByLabel(LabelName labelName) {
046 checkMayRead();
047
048 return writableWorker.getDeclarationsByLabel(labelName);
049 }
050
051 @Override
052 @NotNull
053 public DeclarationDescriptor getContainingDeclaration() {
054 checkMayRead();
055
056 return writableWorker.getContainingDeclaration();
057 }
058
059 @Override
060 @NotNull
061 public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
062 checkMayRead();
063
064 Set<FunctionDescriptor> result = Sets.newLinkedHashSet();
065
066 result.addAll(writableWorker.getFunctions(name));
067
068 result.addAll(getWorkerScope().getFunctions(name));
069
070 result.addAll(super.getFunctions(name)); // Imports
071
072 return result;
073 }
074
075 @Override
076 @NotNull
077 public Set<VariableDescriptor> getProperties(@NotNull Name name) {
078 checkMayRead();
079
080 Set<VariableDescriptor> properties = Sets.newLinkedHashSet();
081 properties.addAll(writableWorker.getProperties(name));
082 properties.addAll(getWorkerScope().getProperties(name));
083 properties.addAll(super.getProperties(name)); //imports
084 return properties;
085 }
086
087 @Override
088 @Nullable
089 public VariableDescriptor getLocalVariable(@NotNull Name name) {
090 checkMayRead();
091
092 VariableDescriptor variable = writableWorker.getLocalVariable(name);
093 if (variable != null) return variable;
094
095 variable = getWorkerScope().getLocalVariable(name);
096 if (variable != null) return variable;
097
098 return super.getLocalVariable(name); // Imports
099 }
100
101 @Override
102 @Nullable
103 public NamespaceDescriptor getNamespace(@NotNull Name name) {
104 checkMayRead();
105
106 NamespaceDescriptor namespace = writableWorker.getNamespace(name);
107 if (namespace != null) return namespace;
108
109 namespace = getWorkerScope().getNamespace(name);
110 if (namespace != null) return namespace;
111
112 return super.getNamespace(name); // Imports
113 }
114
115 @Override
116 @Nullable
117 public ClassifierDescriptor getClassifier(@NotNull Name name) {
118 checkMayRead();
119
120 ClassifierDescriptor classifier = writableWorker.getClassifier(name);
121 if (classifier != null) return classifier;
122
123 classifier = getWorkerScope().getClassifier(name);
124 if (classifier != null) return classifier;
125
126 return super.getClassifier(name); // Imports
127 }
128
129 @Override
130 public void addLabeledDeclaration(@NotNull DeclarationDescriptor descriptor) {
131 checkMayWrite();
132
133 writableWorker.addLabeledDeclaration(descriptor); // TODO : review
134 }
135
136 @Override
137 public void addVariableDescriptor(@NotNull VariableDescriptor variableDescriptor) {
138 checkMayWrite();
139
140 writableWorker.addVariableDescriptor(variableDescriptor);
141 }
142
143 @Override
144 public void addPropertyDescriptor(@NotNull VariableDescriptor propertyDescriptor) {
145 checkMayWrite();
146
147 writableWorker.addPropertyDescriptor(propertyDescriptor);
148 }
149
150 @Override
151 public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
152 checkMayWrite();
153
154 writableWorker.addFunctionDescriptor(functionDescriptor);
155 }
156
157 @Override
158 public void addTypeParameterDescriptor(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
159 checkMayWrite();
160
161 writableWorker.addTypeParameterDescriptor(typeParameterDescriptor);
162 }
163
164 @Override
165 public void addClassifierDescriptor(@NotNull ClassifierDescriptor classDescriptor) {
166 checkMayWrite();
167
168 writableWorker.addClassifierDescriptor(classDescriptor);
169 }
170
171 @Override
172 public void addClassifierAlias(@NotNull Name name, @NotNull ClassifierDescriptor classifierDescriptor) {
173 checkMayWrite();
174
175 writableWorker.addClassifierAlias(name, classifierDescriptor);
176 }
177
178 @Override
179 public void addNamespaceAlias(@NotNull Name name, @NotNull NamespaceDescriptor namespaceDescriptor) {
180 checkMayWrite();
181
182 writableWorker.addNamespaceAlias(name, namespaceDescriptor);
183 }
184
185 @Override
186 public void addVariableAlias(@NotNull Name name, @NotNull VariableDescriptor variableDescriptor) {
187 checkMayWrite();
188
189 writableWorker.addVariableAlias(name, variableDescriptor);
190 }
191
192 @Override
193 public void addFunctionAlias(@NotNull Name name, @NotNull FunctionDescriptor functionDescriptor) {
194 checkMayWrite();
195
196 writableWorker.addFunctionAlias(name, functionDescriptor);
197 }
198
199 @Override
200 public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
201 checkMayWrite();
202
203 writableWorker.addNamespace(namespaceDescriptor);
204 }
205
206 @Override
207 @Nullable
208 public NamespaceDescriptor getDeclaredNamespace(@NotNull Name name) {
209 checkMayRead();
210
211 return writableWorker.getDeclaredNamespace(name);
212 }
213
214 @NotNull
215 @Override
216 public Multimap<Name, DeclarationDescriptor> getDeclaredDescriptorsAccessibleBySimpleName() {
217 return writableWorker.getDeclaredDescriptorsAccessibleBySimpleName();
218 }
219
220 @Override
221 public void importScope(@NotNull JetScope imported) {
222 checkMayWrite();
223
224 super.importScope(imported); //
225 }
226
227 @Override
228 public void setImplicitReceiver(@NotNull ReceiverParameterDescriptor implicitReceiver) {
229 checkMayWrite();
230
231 writableWorker.setImplicitReceiver(implicitReceiver);
232 }
233
234 @NotNull
235 @Override
236 public Collection<DeclarationDescriptor> getAllDescriptors() {
237 checkMayRead();
238
239 if (allDescriptors == null) {
240 allDescriptors = Lists.newArrayList();
241 allDescriptors.addAll(writableWorker.getAllDescriptors());
242 allDescriptors.addAll(getWorkerScope().getAllDescriptors());
243
244 for (JetScope imported : getImports()) {
245 allDescriptors.addAll(imported.getAllDescriptors());
246 }
247 }
248 return allDescriptors;
249 }
250
251 @TestOnly
252 @Override
253 protected void printAdditionalScopeStructure(@NotNull Printer p) {
254 p.print("writableWorker = ");
255 writableWorker.printScopeStructure(p.withholdIndentOnce());
256 }
257 }