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 ClassDescriptor getObjectDescriptor(@NotNull Name name) {
131            checkMayRead();
132    
133            ClassDescriptor objectDescriptor = writableWorker.getObjectDescriptor(name);
134            if (objectDescriptor != null) return objectDescriptor;
135    
136            objectDescriptor = getWorkerScope().getObjectDescriptor(name);
137            if (objectDescriptor != null) return objectDescriptor;
138    
139            return super.getObjectDescriptor(name); // Imports
140        }
141    
142        @NotNull
143        @Override
144        public Set<ClassDescriptor> getObjectDescriptors() {
145            checkMayRead();
146            Set<ClassDescriptor> objectDescriptors = Sets.newHashSet();
147    
148            objectDescriptors.addAll(super.getObjectDescriptors());
149            objectDescriptors.addAll(getWorkerScope().getObjectDescriptors());
150            objectDescriptors.addAll(writableWorker.getObjectDescriptors());
151            return objectDescriptors;
152        }
153    
154        @Override
155        public void addLabeledDeclaration(@NotNull DeclarationDescriptor descriptor) {
156            checkMayWrite();
157    
158            writableWorker.addLabeledDeclaration(descriptor); // TODO : review
159        }
160    
161        @Override
162        public void addVariableDescriptor(@NotNull VariableDescriptor variableDescriptor) {
163            checkMayWrite();
164    
165            writableWorker.addVariableDescriptor(variableDescriptor);
166        }
167    
168        @Override
169        public void addPropertyDescriptor(@NotNull VariableDescriptor propertyDescriptor) {
170            checkMayWrite();
171    
172            writableWorker.addPropertyDescriptor(propertyDescriptor);
173        }
174    
175        @Override
176        public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
177            checkMayWrite();
178    
179            writableWorker.addFunctionDescriptor(functionDescriptor);
180        }
181    
182        @Override
183        public void addTypeParameterDescriptor(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
184            checkMayWrite();
185    
186            writableWorker.addTypeParameterDescriptor(typeParameterDescriptor);
187        }
188    
189        @Override
190        public void addClassifierDescriptor(@NotNull ClassifierDescriptor classDescriptor) {
191            checkMayWrite();
192    
193            writableWorker.addClassifierDescriptor(classDescriptor);
194        }
195    
196        @Override
197        public void addObjectDescriptor(@NotNull ClassDescriptor objectDescriptor) {
198            checkMayWrite();
199    
200            writableWorker.addObjectDescriptor(objectDescriptor);
201        }
202    
203        @Override
204        public void addClassifierAlias(@NotNull Name name, @NotNull ClassifierDescriptor classifierDescriptor) {
205            checkMayWrite();
206    
207            writableWorker.addClassifierAlias(name, classifierDescriptor);
208        }
209    
210        @Override
211        public void addNamespaceAlias(@NotNull Name name, @NotNull NamespaceDescriptor namespaceDescriptor) {
212            checkMayWrite();
213    
214            writableWorker.addNamespaceAlias(name, namespaceDescriptor);
215        }
216    
217        @Override
218        public void addVariableAlias(@NotNull Name name, @NotNull VariableDescriptor variableDescriptor) {
219            checkMayWrite();
220            
221            writableWorker.addVariableAlias(name, variableDescriptor);
222        }
223    
224        @Override
225        public void addFunctionAlias(@NotNull Name name, @NotNull FunctionDescriptor functionDescriptor) {
226            checkMayWrite();
227    
228            writableWorker.addFunctionAlias(name, functionDescriptor);
229        }
230    
231        @Override
232        public void addNamespace(@NotNull NamespaceDescriptor namespaceDescriptor) {
233            checkMayWrite();
234    
235            writableWorker.addNamespace(namespaceDescriptor);
236        }
237    
238        @Override
239        @Nullable
240        public NamespaceDescriptor getDeclaredNamespace(@NotNull Name name) {
241            checkMayRead();
242    
243            return writableWorker.getDeclaredNamespace(name);
244        }
245    
246        @NotNull
247        @Override
248        public Multimap<Name, DeclarationDescriptor> getDeclaredDescriptorsAccessibleBySimpleName() {
249            return writableWorker.getDeclaredDescriptorsAccessibleBySimpleName();
250        }
251    
252        @Override
253        public void importScope(@NotNull JetScope imported) {
254            checkMayWrite();
255    
256            super.importScope(imported); //
257        }
258    
259        @Override
260        public void setImplicitReceiver(@NotNull ReceiverParameterDescriptor implicitReceiver) {
261            checkMayWrite();
262    
263            writableWorker.setImplicitReceiver(implicitReceiver);
264        }
265    
266        @NotNull
267        @Override
268        public Collection<DeclarationDescriptor> getAllDescriptors() {
269            checkMayRead();
270    
271            if (allDescriptors == null) {
272                allDescriptors = Lists.newArrayList();
273                allDescriptors.addAll(writableWorker.getAllDescriptors());
274                allDescriptors.addAll(getWorkerScope().getAllDescriptors());
275    
276                for (JetScope imported : getImports()) {
277                    allDescriptors.addAll(imported.getAllDescriptors());
278                }
279            }
280            return allDescriptors;
281        }
282    
283        @NotNull
284        public JetScope getOuterScope() {
285            checkMayRead();
286    
287            return getWorkerScope();
288        }
289    
290        @TestOnly
291        @Override
292        protected void printAdditionalScopeStructure(@NotNull Printer p) {
293            p.print("writableWorker = ");
294            writableWorker.printScopeStructure(p.withholdIndentOnce());
295        }
296    }