001 /*
002 * Copyright 2010-2014 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.lazy.descriptors;
018
019 import com.google.common.collect.ImmutableSet;
020 import com.google.common.collect.Lists;
021 import kotlin.Function0;
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.descriptors.impl.ConstructorDescriptorImpl;
026 import org.jetbrains.jet.lang.diagnostics.Errors;
027 import org.jetbrains.jet.lang.psi.*;
028 import org.jetbrains.jet.lang.resolve.*;
029 import org.jetbrains.jet.lang.resolve.dataClassUtils.DataClassUtilsPackage;
030 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
031 import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
032 import org.jetbrains.jet.lang.resolve.lazy.declarations.ClassMemberDeclarationProvider;
033 import org.jetbrains.jet.lang.resolve.name.Name;
034 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
035 import org.jetbrains.jet.lang.types.DeferredType;
036 import org.jetbrains.jet.lang.types.JetType;
037 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
038 import org.jetbrains.jet.storage.NullableLazyValue;
039
040 import java.util.*;
041
042 import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.DELEGATION;
043 import static org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
044 import static org.jetbrains.jet.lang.resolve.DelegationResolver.generateDelegatedMembers;
045
046 public class LazyClassMemberScope extends AbstractLazyMemberScope<LazyClassDescriptor, ClassMemberDeclarationProvider> {
047
048 @NotNull
049 private static final Set<ClassKind> GENERATE_CONSTRUCTORS_FOR =
050 ImmutableSet.of(ClassKind.CLASS, ClassKind.ANNOTATION_CLASS, ClassKind.OBJECT,
051 ClassKind.ENUM_CLASS, ClassKind.ENUM_ENTRY, ClassKind.CLASS_OBJECT);
052
053 private interface MemberExtractor<T extends CallableMemberDescriptor> {
054 MemberExtractor<FunctionDescriptor> EXTRACT_FUNCTIONS = new MemberExtractor<FunctionDescriptor>() {
055 @NotNull
056 @Override
057 public Collection<FunctionDescriptor> extract(@NotNull JetType extractFrom, @NotNull Name name) {
058 return extractFrom.getMemberScope().getFunctions(name);
059 }
060 };
061
062 MemberExtractor<PropertyDescriptor> EXTRACT_PROPERTIES = new MemberExtractor<PropertyDescriptor>() {
063 @NotNull
064 @Override
065 public Collection<PropertyDescriptor> extract(@NotNull JetType extractFrom, @NotNull Name name) {
066 //noinspection unchecked
067 return (Collection) extractFrom.getMemberScope().getProperties(name);
068 }
069 };
070
071 @NotNull
072 Collection<T> extract(@NotNull JetType extractFrom, @NotNull Name name);
073 }
074
075 private final NullableLazyValue<ConstructorDescriptor> primaryConstructor;
076
077 public LazyClassMemberScope(
078 @NotNull ResolveSession resolveSession,
079 @NotNull ClassMemberDeclarationProvider declarationProvider,
080 @NotNull LazyClassDescriptor thisClass,
081 @NotNull BindingTrace trace
082 ) {
083 super(resolveSession, declarationProvider, thisClass, trace);
084 this.primaryConstructor = resolveSession.getStorageManager().createNullableLazyValue(new Function0<ConstructorDescriptor>() {
085 @Override
086 public ConstructorDescriptor invoke() {
087 return resolvePrimaryConstructor();
088 }
089 });
090 }
091
092 @NotNull
093 @Override
094 protected JetScope getScopeForMemberDeclarationResolution(JetDeclaration declaration) {
095 if (declaration instanceof JetProperty) {
096 return thisDescriptor.getScopeForInitializerResolution();
097 }
098 return thisDescriptor.getScopeForMemberDeclarationResolution();
099 }
100
101 private <D extends CallableMemberDescriptor> void generateFakeOverrides(
102 @NotNull Name name,
103 @NotNull Collection<D> fromSupertypes,
104 @NotNull final Collection<D> result,
105 @NotNull final Class<? extends D> exactDescriptorClass
106 ) {
107 OverridingUtil.generateOverridesInFunctionGroup(
108 name,
109 fromSupertypes,
110 Lists.newArrayList(result),
111 thisDescriptor,
112 new OverridingUtil.DescriptorSink() {
113 @Override
114 public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
115 assert exactDescriptorClass.isInstance(fakeOverride) : "Wrong descriptor type in an override: " +
116 fakeOverride +
117 " while expecting " +
118 exactDescriptorClass.getSimpleName();
119 //noinspection unchecked
120 result.add((D) fakeOverride);
121 }
122
123 @Override
124 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
125 JetDeclaration declaration = (JetDeclaration) DescriptorToSourceUtils.descriptorToDeclaration(fromCurrent);
126 assert declaration != null : "fromCurrent can not be a fake override";
127 trace.report(Errors.CONFLICTING_OVERLOADS
128 .on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()));
129 }
130 }
131 );
132 OverrideResolver.resolveUnknownVisibilities(result, trace);
133 }
134
135 @NotNull
136 @Override
137 public Set<FunctionDescriptor> getFunctions(@NotNull Name name) {
138 // TODO: this should be handled by lazy function descriptors
139 Set<FunctionDescriptor> functions = super.getFunctions(name);
140 resolveUnknownVisibilitiesForMembers(functions);
141 return functions;
142 }
143
144 @Override
145 protected void getNonDeclaredFunctions(@NotNull Name name, @NotNull Set<FunctionDescriptor> result) {
146 Collection<FunctionDescriptor> fromSupertypes = Lists.newArrayList();
147 for (JetType supertype : thisDescriptor.getTypeConstructor().getSupertypes()) {
148 fromSupertypes.addAll(supertype.getMemberScope().getFunctions(name));
149 }
150 result.addAll(generateDelegatingDescriptors(name, MemberExtractor.EXTRACT_FUNCTIONS, result));
151 generateDataClassMethods(result, name);
152 generateFakeOverrides(name, fromSupertypes, result, FunctionDescriptor.class);
153 }
154
155 private void generateDataClassMethods(@NotNull Collection<FunctionDescriptor> result, @NotNull Name name) {
156 if (!KotlinBuiltIns.getInstance().isData(thisDescriptor)) return;
157
158 ConstructorDescriptor constructor = getPrimaryConstructor();
159 if (constructor == null) return;
160
161 List<? extends JetParameter> primaryConstructorParameters = declarationProvider.getOwnerInfo().getPrimaryConstructorParameters();
162 assert constructor.getValueParameters().size() == primaryConstructorParameters.size()
163 : "From descriptor: " + constructor.getValueParameters().size() + " but from PSI: " + primaryConstructorParameters.size();
164
165 if (DataClassUtilsPackage.isComponentLike(name)) {
166 int componentIndex = 0;
167
168 for (ValueParameterDescriptor parameter : constructor.getValueParameters()) {
169 if (parameter.getType().isError()) continue;
170 if (!primaryConstructorParameters.get(parameter.getIndex()).hasValOrVarNode()) continue;
171
172 Set<VariableDescriptor> properties = getProperties(parameter.getName());
173 if (properties.isEmpty()) continue;
174
175 assert properties.size() == 1 :
176 "A constructor parameter is resolved to more than one (" + properties.size() + ") property: " + parameter;
177
178 PropertyDescriptor property = (PropertyDescriptor) properties.iterator().next();
179 if (property == null) continue;
180
181 ++componentIndex;
182
183 if (name.equals(DataClassUtilsPackage.createComponentName(componentIndex))) {
184 SimpleFunctionDescriptor functionDescriptor = DescriptorResolver.createComponentFunctionDescriptor(
185 componentIndex, property, parameter, thisDescriptor, trace);
186 result.add(functionDescriptor);
187 break;
188 }
189 }
190 }
191
192 if (name.equals(DescriptorResolver.COPY_METHOD_NAME)) {
193 SimpleFunctionDescriptor copyFunctionDescriptor = DescriptorResolver.createCopyFunctionDescriptor(
194 constructor.getValueParameters(),
195 thisDescriptor, trace);
196 result.add(copyFunctionDescriptor);
197 }
198 }
199
200 @NotNull
201 @Override
202 @SuppressWarnings("unchecked")
203 public Set<VariableDescriptor> getProperties(@NotNull Name name) {
204 // TODO: this should be handled by lazy property descriptors
205 Set<VariableDescriptor> properties = super.getProperties(name);
206 resolveUnknownVisibilitiesForMembers((Set) properties);
207 return properties;
208 }
209
210 private void resolveUnknownVisibilitiesForMembers(@NotNull Set<? extends CallableMemberDescriptor> descriptors) {
211 for (CallableMemberDescriptor descriptor : descriptors) {
212 if (descriptor.getKind() != FAKE_OVERRIDE && descriptor.getKind() != DELEGATION) {
213 OverridingUtil.resolveUnknownVisibilityForMember(descriptor, OverrideResolver.createCannotInferVisibilityReporter(trace));
214 }
215 }
216 }
217
218 @Override
219 @SuppressWarnings("unchecked")
220 protected void getNonDeclaredProperties(@NotNull Name name, @NotNull Set<VariableDescriptor> result) {
221 createPropertiesFromPrimaryConstructorParameters(name, result);
222
223 // Members from supertypes
224 Collection<PropertyDescriptor> fromSupertypes = Lists.newArrayList();
225 for (JetType supertype : thisDescriptor.getTypeConstructor().getSupertypes()) {
226 fromSupertypes.addAll((Collection) supertype.getMemberScope().getProperties(name));
227 }
228 result.addAll(generateDelegatingDescriptors(name, MemberExtractor.EXTRACT_PROPERTIES, result));
229 generateFakeOverrides(name, fromSupertypes, (Collection) result, PropertyDescriptor.class);
230 }
231
232 protected void createPropertiesFromPrimaryConstructorParameters(@NotNull Name name, @NotNull Set<VariableDescriptor> result) {
233 JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
234
235 // From primary constructor parameters
236 ConstructorDescriptor primaryConstructor = getPrimaryConstructor();
237 if (primaryConstructor == null) return;
238
239 List<ValueParameterDescriptor> valueParameterDescriptors = primaryConstructor.getValueParameters();
240 List<? extends JetParameter> primaryConstructorParameters = classInfo.getPrimaryConstructorParameters();
241 assert valueParameterDescriptors.size() == primaryConstructorParameters.size()
242 : "From descriptor: " + valueParameterDescriptors.size() + " but from PSI: " + primaryConstructorParameters.size();
243
244 for (ValueParameterDescriptor valueParameterDescriptor : valueParameterDescriptors) {
245 if (!name.equals(valueParameterDescriptor.getName())) continue;
246
247 JetParameter parameter = primaryConstructorParameters.get(valueParameterDescriptor.getIndex());
248 if (parameter.hasValOrVarNode()) {
249 PropertyDescriptor propertyDescriptor =
250 resolveSession.getDescriptorResolver().resolvePrimaryConstructorParameterToAProperty(
251 thisDescriptor,
252 valueParameterDescriptor,
253 thisDescriptor.getScopeForClassHeaderResolution(),
254 parameter, trace
255 );
256 result.add(propertyDescriptor);
257 }
258 }
259 }
260
261 @NotNull
262 private <T extends CallableMemberDescriptor> Collection<T> generateDelegatingDescriptors(
263 @NotNull final Name name,
264 @NotNull final MemberExtractor<T> extractor,
265 @NotNull Collection<? extends CallableDescriptor> existingDescriptors
266 ) {
267 JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
268 if (classOrObject == null) {
269 // Enum class objects do not have delegated members
270 return Collections.emptySet();
271 }
272
273 DelegationResolver.TypeResolver lazyTypeResolver = new DelegationResolver.TypeResolver() {
274 @Nullable
275 @Override
276 public JetType resolve(@NotNull JetTypeReference reference) {
277 return resolveSession.getTypeResolver().resolveType(
278 thisDescriptor.getScopeForClassHeaderResolution(),
279 reference,
280 trace,
281 false);
282 }
283 };
284 DelegationResolver.MemberExtractor<T> lazyMemberExtractor = new DelegationResolver.MemberExtractor<T>() {
285 @NotNull
286 @Override
287 public Collection<T> getMembersByType(@NotNull JetType type) {
288 return extractor.extract(type, name);
289 }
290 };
291 return generateDelegatedMembers(classOrObject, thisDescriptor, existingDescriptors, trace, lazyMemberExtractor,
292 lazyTypeResolver);
293 }
294
295 @Override
296 @NotNull
297 protected Collection<DeclarationDescriptor> computeExtraDescriptors() {
298 ArrayList<DeclarationDescriptor> result = new ArrayList<DeclarationDescriptor>();
299 for (JetType supertype : thisDescriptor.getTypeConstructor().getSupertypes()) {
300 for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
301 if (descriptor instanceof FunctionDescriptor) {
302 result.addAll(getFunctions(descriptor.getName()));
303 }
304 else if (descriptor instanceof PropertyDescriptor) {
305 result.addAll(getProperties(descriptor.getName()));
306 }
307 // Nothing else is inherited
308 }
309 }
310
311 addDataClassMethods(result);
312
313 result.trimToSize();
314 return result;
315 }
316
317 private void addDataClassMethods(@NotNull Collection<DeclarationDescriptor> result) {
318 if (!KotlinBuiltIns.getInstance().isData(thisDescriptor)) return;
319
320 ConstructorDescriptor constructor = getPrimaryConstructor();
321 if (constructor == null) return;
322
323 // Generate componentN functions until there's no such function for some n
324 int n = 1;
325 while (true) {
326 Name componentName = DataClassUtilsPackage.createComponentName(n);
327 Set<FunctionDescriptor> functions = getFunctions(componentName);
328 if (functions.isEmpty()) break;
329
330 result.addAll(functions);
331
332 n++;
333 }
334 result.addAll(getFunctions(Name.identifier("copy")));
335 }
336
337 @Nullable
338 @Override
339 public PackageViewDescriptor getPackage(@NotNull Name name) {
340 return null;
341 }
342
343 @NotNull
344 public Set<ConstructorDescriptor> getConstructors() {
345 ConstructorDescriptor constructor = getPrimaryConstructor();
346 return constructor == null ? Collections.<ConstructorDescriptor>emptySet() : Collections.singleton(constructor);
347 }
348
349 @Nullable
350 public ConstructorDescriptor getPrimaryConstructor() {
351 return primaryConstructor.invoke();
352 }
353
354 @Nullable
355 protected ConstructorDescriptor resolvePrimaryConstructor() {
356 if (GENERATE_CONSTRUCTORS_FOR.contains(thisDescriptor.getKind())) {
357 JetClassLikeInfo ownerInfo = declarationProvider.getOwnerInfo();
358 JetClassOrObject classOrObject = ownerInfo.getCorrespondingClassOrObject();
359 if (!thisDescriptor.getKind().isSingleton()) {
360 JetClass jetClass = (JetClass) classOrObject;
361 assert jetClass != null : "No JetClass for " + thisDescriptor;
362 ConstructorDescriptorImpl constructor = resolveSession.getDescriptorResolver()
363 .resolvePrimaryConstructorDescriptor(thisDescriptor.getScopeForClassHeaderResolution(),
364 thisDescriptor,
365 jetClass,
366 trace);
367 assert constructor != null : "No constructor created for " + thisDescriptor;
368 setDeferredReturnType(constructor);
369 return constructor;
370 }
371 else {
372 ConstructorDescriptorImpl constructor =
373 DescriptorResolver.createAndRecordPrimaryConstructorForObject(classOrObject, thisDescriptor, trace);
374 setDeferredReturnType(constructor);
375 return constructor;
376 }
377 }
378 return null;
379 }
380
381 protected void setDeferredReturnType(@NotNull ConstructorDescriptorImpl descriptor) {
382 descriptor.setReturnType(DeferredType.create(resolveSession.getStorageManager(), trace,
383 new Function0<JetType>() {
384 @Override
385 public JetType invoke() {
386 return thisDescriptor.getDefaultType();
387 }
388 })
389 );
390 }
391
392 @Override
393 public String toString() {
394 // Do not add details here, they may compromise the laziness during debugging
395 return "lazy scope for class " + thisDescriptor.getName();
396 }
397 }