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 for (ValueParameterDescriptor parameter : constructor.getValueParameters()) {
194 // force properties resolution to fill BindingContext.VALUE_PARAMETER_AS_PROPERTY slice
195 getProperties(parameter.getName());
196 }
197
198 SimpleFunctionDescriptor copyFunctionDescriptor =
199 DescriptorResolver.createCopyFunctionDescriptor(constructor.getValueParameters(), thisDescriptor, trace);
200 result.add(copyFunctionDescriptor);
201 }
202 }
203
204 @NotNull
205 @Override
206 @SuppressWarnings("unchecked")
207 public Set<VariableDescriptor> getProperties(@NotNull Name name) {
208 // TODO: this should be handled by lazy property descriptors
209 Set<VariableDescriptor> properties = super.getProperties(name);
210 resolveUnknownVisibilitiesForMembers((Set) properties);
211 return properties;
212 }
213
214 private void resolveUnknownVisibilitiesForMembers(@NotNull Set<? extends CallableMemberDescriptor> descriptors) {
215 for (CallableMemberDescriptor descriptor : descriptors) {
216 if (descriptor.getKind() != FAKE_OVERRIDE && descriptor.getKind() != DELEGATION) {
217 OverridingUtil.resolveUnknownVisibilityForMember(descriptor, OverrideResolver.createCannotInferVisibilityReporter(trace));
218 }
219 }
220 }
221
222 @Override
223 @SuppressWarnings("unchecked")
224 protected void getNonDeclaredProperties(@NotNull Name name, @NotNull Set<VariableDescriptor> result) {
225 createPropertiesFromPrimaryConstructorParameters(name, result);
226
227 // Members from supertypes
228 Collection<PropertyDescriptor> fromSupertypes = Lists.newArrayList();
229 for (JetType supertype : thisDescriptor.getTypeConstructor().getSupertypes()) {
230 fromSupertypes.addAll((Collection) supertype.getMemberScope().getProperties(name));
231 }
232 result.addAll(generateDelegatingDescriptors(name, MemberExtractor.EXTRACT_PROPERTIES, result));
233 generateFakeOverrides(name, fromSupertypes, (Collection) result, PropertyDescriptor.class);
234 }
235
236 protected void createPropertiesFromPrimaryConstructorParameters(@NotNull Name name, @NotNull Set<VariableDescriptor> result) {
237 JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
238
239 // From primary constructor parameters
240 ConstructorDescriptor primaryConstructor = getPrimaryConstructor();
241 if (primaryConstructor == null) return;
242
243 List<ValueParameterDescriptor> valueParameterDescriptors = primaryConstructor.getValueParameters();
244 List<? extends JetParameter> primaryConstructorParameters = classInfo.getPrimaryConstructorParameters();
245 assert valueParameterDescriptors.size() == primaryConstructorParameters.size()
246 : "From descriptor: " + valueParameterDescriptors.size() + " but from PSI: " + primaryConstructorParameters.size();
247
248 for (ValueParameterDescriptor valueParameterDescriptor : valueParameterDescriptors) {
249 if (!name.equals(valueParameterDescriptor.getName())) continue;
250
251 JetParameter parameter = primaryConstructorParameters.get(valueParameterDescriptor.getIndex());
252 if (parameter.hasValOrVarNode()) {
253 PropertyDescriptor propertyDescriptor =
254 resolveSession.getDescriptorResolver().resolvePrimaryConstructorParameterToAProperty(
255 thisDescriptor,
256 valueParameterDescriptor,
257 thisDescriptor.getScopeForClassHeaderResolution(),
258 parameter, trace
259 );
260 result.add(propertyDescriptor);
261 }
262 }
263 }
264
265 @NotNull
266 private <T extends CallableMemberDescriptor> Collection<T> generateDelegatingDescriptors(
267 @NotNull final Name name,
268 @NotNull final MemberExtractor<T> extractor,
269 @NotNull Collection<? extends CallableDescriptor> existingDescriptors
270 ) {
271 JetClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
272 if (classOrObject == null) {
273 // Enum class objects do not have delegated members
274 return Collections.emptySet();
275 }
276
277 DelegationResolver.TypeResolver lazyTypeResolver = new DelegationResolver.TypeResolver() {
278 @Nullable
279 @Override
280 public JetType resolve(@NotNull JetTypeReference reference) {
281 return resolveSession.getTypeResolver().resolveType(
282 thisDescriptor.getScopeForClassHeaderResolution(),
283 reference,
284 trace,
285 false);
286 }
287 };
288 DelegationResolver.MemberExtractor<T> lazyMemberExtractor = new DelegationResolver.MemberExtractor<T>() {
289 @NotNull
290 @Override
291 public Collection<T> getMembersByType(@NotNull JetType type) {
292 return extractor.extract(type, name);
293 }
294 };
295 return generateDelegatedMembers(classOrObject, thisDescriptor, existingDescriptors, trace, lazyMemberExtractor,
296 lazyTypeResolver);
297 }
298
299 @Override
300 @NotNull
301 protected Collection<DeclarationDescriptor> computeExtraDescriptors() {
302 ArrayList<DeclarationDescriptor> result = new ArrayList<DeclarationDescriptor>();
303 for (JetType supertype : thisDescriptor.getTypeConstructor().getSupertypes()) {
304 for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
305 if (descriptor instanceof FunctionDescriptor) {
306 result.addAll(getFunctions(descriptor.getName()));
307 }
308 else if (descriptor instanceof PropertyDescriptor) {
309 result.addAll(getProperties(descriptor.getName()));
310 }
311 // Nothing else is inherited
312 }
313 }
314
315 addDataClassMethods(result);
316
317 result.trimToSize();
318 return result;
319 }
320
321 private void addDataClassMethods(@NotNull Collection<DeclarationDescriptor> result) {
322 if (!KotlinBuiltIns.getInstance().isData(thisDescriptor)) return;
323
324 ConstructorDescriptor constructor = getPrimaryConstructor();
325 if (constructor == null) return;
326
327 // Generate componentN functions until there's no such function for some n
328 int n = 1;
329 while (true) {
330 Name componentName = DataClassUtilsPackage.createComponentName(n);
331 Set<FunctionDescriptor> functions = getFunctions(componentName);
332 if (functions.isEmpty()) break;
333
334 result.addAll(functions);
335
336 n++;
337 }
338 result.addAll(getFunctions(Name.identifier("copy")));
339 }
340
341 @Nullable
342 @Override
343 public PackageViewDescriptor getPackage(@NotNull Name name) {
344 return null;
345 }
346
347 @NotNull
348 public Set<ConstructorDescriptor> getConstructors() {
349 ConstructorDescriptor constructor = getPrimaryConstructor();
350 return constructor == null ? Collections.<ConstructorDescriptor>emptySet() : Collections.singleton(constructor);
351 }
352
353 @Nullable
354 public ConstructorDescriptor getPrimaryConstructor() {
355 return primaryConstructor.invoke();
356 }
357
358 @Nullable
359 protected ConstructorDescriptor resolvePrimaryConstructor() {
360 if (GENERATE_CONSTRUCTORS_FOR.contains(thisDescriptor.getKind())) {
361 JetClassLikeInfo ownerInfo = declarationProvider.getOwnerInfo();
362 JetClassOrObject classOrObject = ownerInfo.getCorrespondingClassOrObject();
363 if (!thisDescriptor.getKind().isSingleton()) {
364 JetClass jetClass = (JetClass) classOrObject;
365 assert jetClass != null : "No JetClass for " + thisDescriptor;
366 ConstructorDescriptorImpl constructor = resolveSession.getDescriptorResolver()
367 .resolvePrimaryConstructorDescriptor(thisDescriptor.getScopeForClassHeaderResolution(),
368 thisDescriptor,
369 jetClass,
370 trace);
371 assert constructor != null : "No constructor created for " + thisDescriptor;
372 setDeferredReturnType(constructor);
373 return constructor;
374 }
375 else {
376 ConstructorDescriptorImpl constructor =
377 DescriptorResolver.createAndRecordPrimaryConstructorForObject(classOrObject, thisDescriptor, trace);
378 setDeferredReturnType(constructor);
379 return constructor;
380 }
381 }
382 return null;
383 }
384
385 protected void setDeferredReturnType(@NotNull ConstructorDescriptorImpl descriptor) {
386 descriptor.setReturnType(DeferredType.create(resolveSession.getStorageManager(), trace,
387 new Function0<JetType>() {
388 @Override
389 public JetType invoke() {
390 return thisDescriptor.getDefaultType();
391 }
392 })
393 );
394 }
395
396 @Override
397 public String toString() {
398 // Do not add details here, they may compromise the laziness during debugging
399 return "lazy scope for class " + thisDescriptor.getName();
400 }
401 }