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