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