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