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.*;
020 import org.jetbrains.annotations.NotNull;
021 import org.jetbrains.annotations.Nullable;
022 import org.jetbrains.jet.lang.descriptors.*;
023 import org.jetbrains.jet.lang.resolve.name.Name;
024 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
025 import org.jetbrains.jet.utils.Printer;
026
027 import java.util.*;
028
029 // Reads from:
030 // 1. Maps
031 // 2. Worker
032 // 3. Imports
033
034 // Writes to: maps
035
036 public class WritableScopeImpl extends WritableScopeWithImports {
037
038 private final Collection<DeclarationDescriptor> allDescriptors = Lists.newArrayList();
039 private final Multimap<Name, DeclarationDescriptor> declaredDescriptorsAccessibleBySimpleName = HashMultimap.create();
040 private boolean allDescriptorsDone = false;
041
042 @NotNull
043 private final DeclarationDescriptor ownerDeclarationDescriptor;
044
045 @Nullable
046 private SetMultimap<Name, FunctionDescriptor> functionGroups;
047
048 @Nullable
049 private Map<Name, DeclarationDescriptor> variableOrClassDescriptors;
050
051 @Nullable
052 private SetMultimap<Name, VariableDescriptor> propertyGroups;
053
054 @Nullable
055 private Map<Name, PackageViewDescriptor> packageAliases;
056
057 @Nullable
058 private Map<Name, List<DeclarationDescriptor>> labelsToDescriptors;
059
060 @Nullable
061 private ReceiverParameterDescriptor implicitReceiver;
062
063 public WritableScopeImpl(@NotNull JetScope scope, @NotNull DeclarationDescriptor owner,
064 @NotNull RedeclarationHandler redeclarationHandler, @NotNull String debugName) {
065 super(scope, redeclarationHandler, debugName);
066 this.ownerDeclarationDescriptor = owner;
067 }
068
069 @NotNull
070 @Override
071 public DeclarationDescriptor getContainingDeclaration() {
072 return ownerDeclarationDescriptor;
073 }
074
075 @Override
076 public void importScope(@NotNull JetScope imported) {
077 checkMayWrite();
078 super.importScope(imported);
079 }
080
081 @Override
082 public void importClassifierAlias(@NotNull Name importedClassifierName, @NotNull ClassifierDescriptor classifierDescriptor) {
083 checkMayWrite();
084
085 allDescriptors.add(classifierDescriptor);
086 super.importClassifierAlias(importedClassifierName, classifierDescriptor);
087 }
088
089 @Override
090 public void importPackageAlias(@NotNull Name aliasName, @NotNull PackageViewDescriptor packageView) {
091 checkMayWrite();
092
093 allDescriptors.add(packageView);
094 super.importPackageAlias(aliasName, packageView);
095 }
096
097 @Override
098 public void importFunctionAlias(@NotNull Name aliasName, @NotNull FunctionDescriptor functionDescriptor) {
099 checkMayWrite();
100
101 addFunctionDescriptor(functionDescriptor);
102 super.importFunctionAlias(aliasName, functionDescriptor);
103
104 }
105
106 @Override
107 public void importVariableAlias(@NotNull Name aliasName, @NotNull VariableDescriptor variableDescriptor) {
108 checkMayWrite();
109
110 addPropertyDescriptor(variableDescriptor);
111 super.importVariableAlias(aliasName, variableDescriptor);
112 }
113
114 @Override
115 public void clearImports() {
116 checkMayWrite();
117
118 super.clearImports();
119 }
120
121 @NotNull
122 @Override
123 public Collection<DeclarationDescriptor> getAllDescriptors() {
124 checkMayRead();
125
126 if (!allDescriptorsDone) {
127 allDescriptorsDone = true;
128
129 // make sure no descriptors added to allDescriptors collection
130 changeLockLevel(LockLevel.READING);
131
132 allDescriptors.addAll(getWorkerScope().getAllDescriptors());
133 for (JetScope imported : getImports()) {
134 allDescriptors.addAll(imported.getAllDescriptors());
135 }
136 }
137 return allDescriptors;
138 }
139
140 @NotNull
141 private Map<Name, List<DeclarationDescriptor>> getLabelsToDescriptors() {
142 if (labelsToDescriptors == null) {
143 labelsToDescriptors = new HashMap<Name, List<DeclarationDescriptor>>();
144 }
145 return labelsToDescriptors;
146 }
147
148 @NotNull
149 @Override
150 public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull Name labelName) {
151 checkMayRead();
152
153 Collection<DeclarationDescriptor> superResult = super.getDeclarationsByLabel(labelName);
154 Map<Name, List<DeclarationDescriptor>> labelsToDescriptors = getLabelsToDescriptors();
155 List<DeclarationDescriptor> declarationDescriptors = labelsToDescriptors.get(labelName);
156 if (declarationDescriptors == null) {
157 return superResult;
158 }
159 if (superResult.isEmpty()) return declarationDescriptors;
160 List<DeclarationDescriptor> result = new ArrayList<DeclarationDescriptor>(declarationDescriptors);
161 result.addAll(superResult);
162 return result;
163 }
164
165 @Override
166 public void addLabeledDeclaration(@NotNull DeclarationDescriptor descriptor) {
167 checkMayWrite();
168
169 Map<Name, List<DeclarationDescriptor>> labelsToDescriptors = getLabelsToDescriptors();
170 Name name = descriptor.getName();
171 List<DeclarationDescriptor> declarationDescriptors = labelsToDescriptors.get(name);
172 if (declarationDescriptors == null) {
173 declarationDescriptors = new ArrayList<DeclarationDescriptor>();
174 labelsToDescriptors.put(name, declarationDescriptors);
175 }
176 declarationDescriptors.add(descriptor);
177 }
178
179 @NotNull
180 private Map<Name, DeclarationDescriptor> getVariableOrClassDescriptors() {
181 if (variableOrClassDescriptors == null) {
182 variableOrClassDescriptors = Maps.newHashMap();
183 }
184 return variableOrClassDescriptors;
185 }
186
187 @NotNull
188 private Map<Name, PackageViewDescriptor> getPackageAliases() {
189 if (packageAliases == null) {
190 packageAliases = Maps.newHashMap();
191 }
192 return packageAliases;
193 }
194
195 @Override
196 public void addVariableDescriptor(@NotNull VariableDescriptor variableDescriptor) {
197 addVariableDescriptor(variableDescriptor, false);
198 }
199
200 @Override
201 public void addPropertyDescriptor(@NotNull VariableDescriptor propertyDescriptor) {
202 addVariableDescriptor(propertyDescriptor, true);
203 }
204
205 private void addVariableDescriptor(@NotNull VariableDescriptor variableDescriptor, boolean isProperty) {
206 checkMayWrite();
207
208 Name name = variableDescriptor.getName();
209 if (isProperty) {
210 checkForPropertyRedeclaration(name, variableDescriptor);
211 getPropertyGroups().put(name, variableDescriptor);
212 }
213 if (variableDescriptor.getReceiverParameter() == null) {
214 checkForRedeclaration(name, variableDescriptor);
215 // TODO : Should this always happen?
216 getVariableOrClassDescriptors().put(name, variableDescriptor);
217 }
218 allDescriptors.add(variableDescriptor);
219 addToDeclared(variableDescriptor);
220 }
221
222 @NotNull
223 @Override
224 public Set<VariableDescriptor> getProperties(@NotNull Name name) {
225 checkMayRead();
226
227 Set<VariableDescriptor> result = Sets.newLinkedHashSet(getPropertyGroups().get(name));
228
229 result.addAll(getWorkerScope().getProperties(name));
230
231 result.addAll(super.getProperties(name));
232
233 return result;
234 }
235
236 @Override
237 public VariableDescriptor getLocalVariable(@NotNull Name name) {
238 checkMayRead();
239
240 Map<Name, DeclarationDescriptor> variableOrClassDescriptors = getVariableOrClassDescriptors();
241 DeclarationDescriptor descriptor = variableOrClassDescriptors.get(name);
242 if (descriptor instanceof VariableDescriptor && !getPropertyGroups().get(name).contains(descriptor)) {
243 return (VariableDescriptor) descriptor;
244 }
245
246 VariableDescriptor variableDescriptor = getWorkerScope().getLocalVariable(name);
247 if (variableDescriptor != null) {
248 return variableDescriptor;
249 }
250 return super.getLocalVariable(name);
251 }
252
253 @NotNull
254 private SetMultimap<Name, VariableDescriptor> getPropertyGroups() {
255 if (propertyGroups == null) {
256 propertyGroups = LinkedHashMultimap.create();
257 }
258 return propertyGroups;
259 }
260
261 @NotNull
262 private SetMultimap<Name, FunctionDescriptor> getFunctionGroups() {
263 if (functionGroups == null) {
264 functionGroups = LinkedHashMultimap.create();
265 }
266 return functionGroups;
267 }
268
269 @Override
270 public void addFunctionDescriptor(@NotNull FunctionDescriptor functionDescriptor) {
271 checkMayWrite();
272
273 getFunctionGroups().put(functionDescriptor.getName(), functionDescriptor);
274 allDescriptors.add(functionDescriptor);
275 }
276
277 @Override
278 @NotNull
279 public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
280 checkMayRead();
281
282 Set<FunctionDescriptor> result = Sets.newLinkedHashSet(getFunctionGroups().get(name));
283
284 result.addAll(getWorkerScope().getFunctions(name));
285
286 result.addAll(super.getFunctions(name));
287
288 return result;
289 }
290
291 @Override
292 public void addTypeParameterDescriptor(@NotNull TypeParameterDescriptor typeParameterDescriptor) {
293 checkMayWrite();
294
295 Name name = typeParameterDescriptor.getName();
296 addClassifierAlias(name, typeParameterDescriptor);
297 }
298
299 @Override
300 public void addClassifierDescriptor(@NotNull ClassifierDescriptor classDescriptor) {
301 checkMayWrite();
302
303 addClassifierAlias(classDescriptor.getName(), classDescriptor);
304 }
305
306 @Override
307 public void addClassifierAlias(@NotNull Name name, @NotNull ClassifierDescriptor classifierDescriptor) {
308 checkMayWrite();
309
310 checkForRedeclaration(name, classifierDescriptor);
311 getVariableOrClassDescriptors().put(name, classifierDescriptor);
312 allDescriptors.add(classifierDescriptor);
313 addToDeclared(classifierDescriptor);
314 }
315
316 @Override
317 public void addPackageAlias(@NotNull Name name, @NotNull PackageViewDescriptor packageView) {
318 checkMayWrite();
319
320 checkForRedeclaration(name, packageView);
321 getPackageAliases().put(name, packageView);
322 allDescriptors.add(packageView);
323 addToDeclared(packageView);
324 }
325
326 @Override
327 public void addFunctionAlias(@NotNull Name name, @NotNull FunctionDescriptor functionDescriptor) {
328 checkMayWrite();
329
330 checkForRedeclaration(name, functionDescriptor);
331 getFunctionGroups().put(name, functionDescriptor);
332 allDescriptors.add(functionDescriptor);
333 }
334
335 @Override
336 public void addVariableAlias(@NotNull Name name, @NotNull VariableDescriptor variableDescriptor) {
337 checkMayWrite();
338
339 checkForRedeclaration(name, variableDescriptor);
340
341 getVariableOrClassDescriptors().put(name, variableDescriptor);
342 getPropertyGroups().put(name, variableDescriptor);
343
344 allDescriptors.add(variableDescriptor);
345 addToDeclared(variableDescriptor);
346 }
347
348 private void checkForPropertyRedeclaration(@NotNull Name name, VariableDescriptor variableDescriptor) {
349 Set<VariableDescriptor> properties = getPropertyGroups().get(name);
350 ReceiverParameterDescriptor receiverParameter = variableDescriptor.getReceiverParameter();
351 for (VariableDescriptor oldProperty : properties) {
352 ReceiverParameterDescriptor receiverParameterForOldVariable = oldProperty.getReceiverParameter();
353 if (((receiverParameter != null && receiverParameterForOldVariable != null) &&
354 (JetTypeChecker.DEFAULT.equalTypes(receiverParameter.getType(), receiverParameterForOldVariable.getType())))) {
355 redeclarationHandler.handleRedeclaration(oldProperty, variableDescriptor);
356 }
357 }
358 }
359
360 private void checkForRedeclaration(@NotNull Name name, DeclarationDescriptor classifierDescriptor) {
361 DeclarationDescriptor originalDescriptor = getVariableOrClassDescriptors().get(name);
362 if (originalDescriptor != null) {
363 redeclarationHandler.handleRedeclaration(originalDescriptor, classifierDescriptor);
364 }
365 }
366
367 @Override
368 public ClassifierDescriptor getClassifier(@NotNull Name name) {
369 checkMayRead();
370
371 Map<Name, DeclarationDescriptor> variableOrClassDescriptors = getVariableOrClassDescriptors();
372 DeclarationDescriptor descriptor = variableOrClassDescriptors.get(name);
373 if (descriptor instanceof ClassifierDescriptor) return (ClassifierDescriptor) descriptor;
374
375 ClassifierDescriptor classifierDescriptor = getWorkerScope().getClassifier(name);
376 if (classifierDescriptor != null) return classifierDescriptor;
377
378 return super.getClassifier(name);
379 }
380
381 @Override
382 public PackageViewDescriptor getPackage(@NotNull Name name) {
383 checkMayRead();
384
385 PackageViewDescriptor aliased = getPackageAliases().get(name);
386 if (aliased != null) return aliased;
387
388 PackageViewDescriptor packageView = getWorkerScope().getPackage(name);
389 if (packageView != null) return packageView;
390 return super.getPackage(name);
391 }
392
393 @Override
394 public void setImplicitReceiver(@NotNull ReceiverParameterDescriptor implicitReceiver) {
395 checkMayWrite();
396
397 if (this.implicitReceiver != null) {
398 throw new UnsupportedOperationException("Receiver redeclared");
399 }
400 this.implicitReceiver = implicitReceiver;
401 }
402
403 @Override
404 protected List<ReceiverParameterDescriptor> computeImplicitReceiversHierarchy() {
405 List<ReceiverParameterDescriptor> implicitReceiverHierarchy = Lists.newArrayList();
406 if (implicitReceiver != null) {
407 implicitReceiverHierarchy.add(implicitReceiver);
408 }
409 implicitReceiverHierarchy.addAll(super.computeImplicitReceiversHierarchy());
410 return implicitReceiverHierarchy;
411 }
412
413 private void addToDeclared(DeclarationDescriptor descriptor) {
414 declaredDescriptorsAccessibleBySimpleName.put(descriptor.getName(), descriptor);
415 }
416
417 @NotNull
418 @Override
419 public Multimap<Name, DeclarationDescriptor> getDeclaredDescriptorsAccessibleBySimpleName() {
420 return declaredDescriptorsAccessibleBySimpleName;
421 }
422
423 @NotNull
424 @Override
425 public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() {
426 return declaredDescriptorsAccessibleBySimpleName.values();
427 }
428
429 @Override
430 protected void printAdditionalScopeStructure(@NotNull Printer p) {
431 p.println("allDescriptorsDone = ", allDescriptorsDone);
432 }
433 }