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    }