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