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