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 017package org.jetbrains.jet.lang.resolve.scopes; 018 019import com.google.common.collect.Lists; 020import com.google.common.collect.Sets; 021import org.jetbrains.annotations.NotNull; 022import org.jetbrains.jet.lang.descriptors.*; 023import org.jetbrains.jet.lang.resolve.name.LabelName; 024import org.jetbrains.jet.lang.resolve.name.Name; 025 026import java.util.Collection; 027import java.util.Collections; 028import java.util.List; 029import java.util.Set; 030 031public class ChainedScope implements JetScope { 032 private final DeclarationDescriptor containingDeclaration; 033 private final String debugName; 034 private final JetScope[] scopeChain; 035 private Collection<DeclarationDescriptor> allDescriptors; 036 private List<ReceiverParameterDescriptor> implicitReceiverHierarchy; 037 038 public ChainedScope(DeclarationDescriptor containingDeclaration, JetScope... scopes) { 039 this(containingDeclaration, "Untitled chained scope", scopes); 040 } 041 042 public ChainedScope(DeclarationDescriptor containingDeclaration, String debugName, JetScope... scopes) { 043 this.containingDeclaration = containingDeclaration; 044 scopeChain = scopes.clone(); 045 046 this.debugName = debugName; 047 } 048 049 @Override 050 public ClassifierDescriptor getClassifier(@NotNull Name name) { 051 for (JetScope scope : scopeChain) { 052 ClassifierDescriptor classifier = scope.getClassifier(name); 053 if (classifier != null) return classifier; 054 } 055 return null; 056 } 057 058 @Override 059 public ClassDescriptor getObjectDescriptor(@NotNull Name name) { 060 for (JetScope scope : scopeChain) { 061 ClassDescriptor objectDescriptor = scope.getObjectDescriptor(name); 062 if (objectDescriptor != null) return objectDescriptor; 063 } 064 return null; 065 } 066 067 @NotNull 068 @Override 069 public Set<ClassDescriptor> getObjectDescriptors() { 070 Set<ClassDescriptor> objectDescriptors = Sets.newHashSet(); 071 for (JetScope scope : scopeChain) { 072 objectDescriptors.addAll(scope.getObjectDescriptors()); 073 } 074 return objectDescriptors; 075 } 076 077 @Override 078 public NamespaceDescriptor getNamespace(@NotNull Name name) { 079 for (JetScope jetScope : scopeChain) { 080 NamespaceDescriptor namespace = jetScope.getNamespace(name); 081 if (namespace != null) { 082 return namespace; 083 } 084 } 085 return null; 086 } 087 088 @NotNull 089 @Override 090 public Set<VariableDescriptor> getProperties(@NotNull Name name) { 091 Set<VariableDescriptor> properties = Sets.newLinkedHashSet(); 092 for (JetScope jetScope : scopeChain) { 093 properties.addAll(jetScope.getProperties(name)); 094 } 095 return properties; 096 } 097 098 @Override 099 public VariableDescriptor getLocalVariable(@NotNull Name name) { 100 for (JetScope jetScope : scopeChain) { 101 VariableDescriptor variable = jetScope.getLocalVariable(name); 102 if (variable != null) { 103 return variable; 104 } 105 } 106 return null; 107 } 108 109 @NotNull 110 @Override 111 public Set<FunctionDescriptor> getFunctions(@NotNull Name name) { 112 if (scopeChain.length == 0) { 113 return Collections.emptySet(); 114 } 115 116 Set<FunctionDescriptor> result = Sets.newLinkedHashSet(); 117 for (JetScope jetScope : scopeChain) { 118 result.addAll(jetScope.getFunctions(name)); 119 } 120 return result; 121 } 122 123 @NotNull 124 @Override 125 public List<ReceiverParameterDescriptor> getImplicitReceiversHierarchy() { 126 if (implicitReceiverHierarchy == null) { 127 implicitReceiverHierarchy = Lists.newArrayList(); 128 for (JetScope jetScope : scopeChain) { 129 implicitReceiverHierarchy.addAll(jetScope.getImplicitReceiversHierarchy()); 130 } 131 } 132 return implicitReceiverHierarchy; 133 } 134 135 @NotNull 136 @Override 137 public DeclarationDescriptor getContainingDeclaration() { 138 return containingDeclaration; 139 } 140 141 @NotNull 142 @Override 143 public Collection<DeclarationDescriptor> getDeclarationsByLabel(@NotNull LabelName labelName) { 144 for (JetScope jetScope : scopeChain) { 145 Collection<DeclarationDescriptor> declarationsByLabel = jetScope.getDeclarationsByLabel(labelName); 146 if (!declarationsByLabel.isEmpty()) return declarationsByLabel; // TODO : merge? 147 } 148 return Collections.emptyList(); 149 } 150 151 @Override 152 public PropertyDescriptor getPropertyByFieldReference(@NotNull Name fieldName) { 153 for (JetScope jetScope : scopeChain) { 154 PropertyDescriptor propertyByFieldReference = jetScope.getPropertyByFieldReference(fieldName); 155 if (propertyByFieldReference != null) { 156 return propertyByFieldReference; 157 } 158 } 159 return null; 160 } 161 162 @NotNull 163 @Override 164 public Collection<DeclarationDescriptor> getAllDescriptors() { 165 if (allDescriptors == null) { 166 allDescriptors = Sets.newHashSet(); 167 for (JetScope scope : scopeChain) { 168 allDescriptors.addAll(scope.getAllDescriptors()); 169 } 170 } 171 return allDescriptors; 172 } 173 174 @NotNull 175 @Override 176 public Collection<DeclarationDescriptor> getOwnDeclaredDescriptors() { 177 throw new UnsupportedOperationException(); 178 } 179 180 @Override 181 public String toString() { 182 return debugName; 183 } 184}