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