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