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