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