001 /*
002 * Copyright 2010-2013 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;
018
019 import com.google.common.base.Function;
020 import com.google.common.base.Predicate;
021 import com.google.common.collect.*;
022 import com.intellij.openapi.util.Pair;
023 import com.intellij.psi.PsiElement;
024 import com.intellij.util.containers.ContainerUtil;
025 import kotlin.Function1;
026 import kotlin.KotlinPackage;
027 import org.jetbrains.annotations.NotNull;
028 import org.jetbrains.annotations.Nullable;
029 import org.jetbrains.jet.lang.descriptors.*;
030 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
031 import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
032 import org.jetbrains.jet.lang.descriptors.impl.PackageLikeBuilder;
033 import org.jetbrains.jet.lang.diagnostics.Errors;
034 import org.jetbrains.jet.lang.psi.*;
035 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
036 import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
037 import org.jetbrains.jet.lang.resolve.name.FqName;
038 import org.jetbrains.jet.lang.resolve.name.Name;
039 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
040 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
041 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
042 import org.jetbrains.jet.renderer.DescriptorRenderer;
043
044 import javax.inject.Inject;
045 import java.util.*;
046
047 import static org.jetbrains.jet.lang.diagnostics.Errors.REDECLARATION;
048
049 public class DeclarationResolver {
050 @NotNull
051 private AnnotationResolver annotationResolver;
052 @NotNull
053 private ImportsResolver importsResolver;
054 @NotNull
055 private DescriptorResolver descriptorResolver;
056 @NotNull
057 private ScriptHeaderResolver scriptHeaderResolver;
058 @NotNull
059 private BindingTrace trace;
060
061
062 @Inject
063 public void setAnnotationResolver(@NotNull AnnotationResolver annotationResolver) {
064 this.annotationResolver = annotationResolver;
065 }
066
067 @Inject
068 public void setImportsResolver(@NotNull ImportsResolver importsResolver) {
069 this.importsResolver = importsResolver;
070 }
071
072 @Inject
073 public void setDescriptorResolver(@NotNull DescriptorResolver descriptorResolver) {
074 this.descriptorResolver = descriptorResolver;
075 }
076
077 @Inject
078 public void setTrace(@NotNull BindingTrace trace) {
079 this.trace = trace;
080 }
081
082 @Inject
083 public void setScriptHeaderResolver(@NotNull ScriptHeaderResolver scriptHeaderResolver) {
084 this.scriptHeaderResolver = scriptHeaderResolver;
085 }
086
087
088
089 public void process(@NotNull TopDownAnalysisContext c) {
090 resolveAnnotationConstructors(c);
091 resolveConstructorHeaders(c);
092 resolveAnnotationStubsOnClassesAndConstructors(c);
093 resolveFunctionAndPropertyHeaders(c);
094 createFunctionsForDataClasses(c);
095 importsResolver.processMembersImports(c);
096 checkRedeclarationsInPackages(c);
097 checkRedeclarationsInInnerClassNames(c);
098 }
099
100 private void resolveAnnotationConstructors(@NotNull TopDownAnalysisContext c) {
101 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getClasses().entrySet()) {
102 JetClassOrObject classOrObject = entry.getKey();
103 MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue();
104
105 if (classOrObject instanceof JetClass && DescriptorUtils.isAnnotationClass(classDescriptor)) {
106 processPrimaryConstructor(c, classDescriptor, (JetClass) classOrObject);
107 }
108 }
109 }
110
111 private void resolveConstructorHeaders(@NotNull TopDownAnalysisContext c) {
112 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getClasses().entrySet()) {
113 JetClassOrObject classOrObject = entry.getKey();
114 MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue();
115
116 if (classOrObject instanceof JetClass && !DescriptorUtils.isAnnotationClass(classDescriptor)) {
117 processPrimaryConstructor(c, classDescriptor, (JetClass) classOrObject);
118 }
119 }
120 }
121
122 private void resolveAnnotationStubsOnClassesAndConstructors(@NotNull TopDownAnalysisContext c) {
123 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getClasses().entrySet()) {
124 JetModifierList modifierList = entry.getKey().getModifierList();
125 if (modifierList != null) {
126 MutableClassDescriptor descriptor = (MutableClassDescriptor) entry.getValue();
127 descriptor.addAnnotations(annotationResolver.resolveAnnotationsWithoutArguments(
128 descriptor.getScopeForClassHeaderResolution(), modifierList, trace));
129 }
130 }
131 }
132
133 private void resolveFunctionAndPropertyHeaders(@NotNull TopDownAnalysisContext c) {
134 for (Map.Entry<JetFile, WritableScope> entry : c.getFileScopes().entrySet()) {
135 JetFile file = entry.getKey();
136 WritableScope fileScope = entry.getValue();
137 PackageLikeBuilder packageBuilder = c.getPackageFragments().get(file).getBuilder();
138
139 resolveFunctionAndPropertyHeaders(c, file.getDeclarations(), fileScope, fileScope, fileScope, packageBuilder);
140 }
141 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getClasses().entrySet()) {
142 JetClassOrObject classOrObject = entry.getKey();
143 MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue();
144
145 resolveFunctionAndPropertyHeaders(
146 c,
147 classOrObject.getDeclarations(), classDescriptor.getScopeForMemberDeclarationResolution(),
148 classDescriptor.getScopeForInitializerResolution(), classDescriptor.getScopeForMemberDeclarationResolution(),
149 classDescriptor.getBuilder());
150 }
151
152 scriptHeaderResolver.resolveScriptDeclarations(c);
153
154 // TODO : Extensions
155 }
156
157 private void resolveFunctionAndPropertyHeaders(
158 @NotNull final TopDownAnalysisContext c,
159 @NotNull List<JetDeclaration> declarations,
160 @NotNull final JetScope scopeForFunctions,
161 @NotNull final JetScope scopeForPropertyInitializers,
162 @NotNull final JetScope scopeForPropertyAccessors,
163 @NotNull final PackageLikeBuilder packageLike)
164 {
165 for (JetDeclaration declaration : declarations) {
166 declaration.accept(new JetVisitorVoid() {
167 @Override
168 public void visitNamedFunction(@NotNull JetNamedFunction function) {
169 SimpleFunctionDescriptor functionDescriptor = descriptorResolver.resolveFunctionDescriptor(
170 packageLike.getOwnerForChildren(),
171 scopeForFunctions,
172 function,
173 trace,
174 c.getOuterDataFlowInfo()
175 );
176 packageLike.addFunctionDescriptor(functionDescriptor);
177 c.getFunctions().put(function, functionDescriptor);
178 c.registerDeclaringScope(function, scopeForFunctions);
179 }
180
181 @Override
182 public void visitProperty(@NotNull JetProperty property) {
183 PropertyDescriptor propertyDescriptor = descriptorResolver.resolvePropertyDescriptor(
184 packageLike.getOwnerForChildren(),
185 scopeForPropertyInitializers,
186 property,
187 trace,
188 c.getOuterDataFlowInfo());
189 packageLike.addPropertyDescriptor(propertyDescriptor);
190 c.getProperties().put(property, propertyDescriptor);
191 c.registerDeclaringScope(property, scopeForPropertyInitializers);
192 JetPropertyAccessor getter = property.getGetter();
193 if (getter != null) {
194 c.registerDeclaringScope(getter, scopeForPropertyAccessors);
195 }
196 JetPropertyAccessor setter = property.getSetter();
197 if (setter != null) {
198 c.registerDeclaringScope(setter, scopeForPropertyAccessors);
199 }
200 }
201 });
202 }
203 }
204
205 private void createFunctionsForDataClasses(@NotNull TopDownAnalysisContext c) {
206 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getClasses().entrySet()) {
207 JetClassOrObject klass = entry.getKey();
208 MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue();
209
210 if (klass instanceof JetClass && klass.hasPrimaryConstructor() && KotlinBuiltIns.getInstance().isData(classDescriptor)) {
211 ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(classDescriptor);
212 createComponentFunctions(classDescriptor, constructor);
213 createCopyFunction(classDescriptor, constructor);
214 }
215 }
216 }
217
218 private void createComponentFunctions(@NotNull MutableClassDescriptor classDescriptor, @NotNull ConstructorDescriptor constructorDescriptor) {
219 int parameterIndex = 0;
220 for (ValueParameterDescriptor parameter : constructorDescriptor.getValueParameters()) {
221 if (!parameter.getType().isError()) {
222 PropertyDescriptor property = trace.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter);
223 if (property != null) {
224 ++parameterIndex;
225
226 SimpleFunctionDescriptor functionDescriptor =
227 DescriptorResolver.createComponentFunctionDescriptor(parameterIndex, property, parameter, classDescriptor, trace);
228
229 classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor);
230 }
231 }
232 }
233 }
234
235 private void createCopyFunction(@NotNull MutableClassDescriptor classDescriptor, @NotNull ConstructorDescriptor constructorDescriptor) {
236 SimpleFunctionDescriptor functionDescriptor = DescriptorResolver.createCopyFunctionDescriptor(
237 constructorDescriptor.getValueParameters(), classDescriptor, trace);
238
239 classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor);
240 }
241
242 private void processPrimaryConstructor(
243 @NotNull TopDownAnalysisContext c,
244 @NotNull MutableClassDescriptor classDescriptor,
245 @NotNull JetClass klass
246 ) {
247 // TODO : not all the parameters are real properties
248 JetScope memberScope = classDescriptor.getScopeForClassHeaderResolution();
249 ConstructorDescriptor constructorDescriptor = descriptorResolver.resolvePrimaryConstructorDescriptor(memberScope, classDescriptor, klass, trace);
250 if (constructorDescriptor != null) {
251 List<ValueParameterDescriptor> valueParameterDescriptors = constructorDescriptor.getValueParameters();
252 List<JetParameter> primaryConstructorParameters = klass.getPrimaryConstructorParameters();
253 assert valueParameterDescriptors.size() == primaryConstructorParameters.size();
254 List<ValueParameterDescriptor> notProperties = new ArrayList<ValueParameterDescriptor>();
255 for (ValueParameterDescriptor valueParameterDescriptor : valueParameterDescriptors) {
256 JetParameter parameter = primaryConstructorParameters.get(valueParameterDescriptor.getIndex());
257 if (parameter.getValOrVarNode() != null) {
258 PropertyDescriptor propertyDescriptor = descriptorResolver.resolvePrimaryConstructorParameterToAProperty(
259 classDescriptor,
260 valueParameterDescriptor,
261 memberScope,
262 parameter, trace
263 );
264 classDescriptor.getBuilder().addPropertyDescriptor(propertyDescriptor);
265 c.getPrimaryConstructorParameterProperties().put(parameter, propertyDescriptor);
266 }
267 else {
268 notProperties.add(valueParameterDescriptor);
269 }
270 }
271
272 if (classDescriptor.getKind() != ClassKind.TRAIT) {
273 classDescriptor.setPrimaryConstructor(constructorDescriptor);
274 classDescriptor.addConstructorParametersToInitializersScope(notProperties);
275 }
276 }
277 }
278
279 private void checkRedeclarationsInPackages(@NotNull TopDownAnalysisContext c) {
280 for (MutablePackageFragmentDescriptor packageFragment : Sets.newHashSet(c.getPackageFragments().values())) {
281 PackageViewDescriptor packageView = packageFragment.getContainingDeclaration().getPackage(packageFragment.getFqName());
282 JetScope packageViewScope = packageView.getMemberScope();
283 Multimap<Name, DeclarationDescriptor> simpleNameDescriptors = packageFragment.getMemberScope().getDeclaredDescriptorsAccessibleBySimpleName();
284 for (Name name : simpleNameDescriptors.keySet()) {
285 // Keep only properties with no receiver
286 Collection<DeclarationDescriptor> descriptors = Collections2.filter(simpleNameDescriptors.get(name), new Predicate<DeclarationDescriptor>() {
287 @Override
288 public boolean apply(@Nullable DeclarationDescriptor descriptor) {
289 if (descriptor instanceof PropertyDescriptor) {
290 PropertyDescriptor propertyDescriptor = (PropertyDescriptor)descriptor;
291 return propertyDescriptor.getReceiverParameter() == null;
292 }
293 return true;
294 }
295 });
296 ContainerUtil.addIfNotNull(descriptors, packageViewScope.getPackage(name));
297
298 if (descriptors.size() > 1) {
299 for (DeclarationDescriptor declarationDescriptor : descriptors) {
300 for (PsiElement declaration : getDeclarationsByDescriptor(declarationDescriptor)) {
301 assert declaration != null : "Null declaration for descriptor: " + declarationDescriptor + " " +
302 (declarationDescriptor != null ? DescriptorRenderer.TEXT.render(declarationDescriptor) : "");
303 trace.report(REDECLARATION.on(declaration, declarationDescriptor.getName().asString()));
304 }
305 }
306 }
307 }
308 }
309 }
310
311 @NotNull
312 private Collection<PsiElement> getDeclarationsByDescriptor(@NotNull DeclarationDescriptor declarationDescriptor) {
313 Collection<PsiElement> declarations;
314 if (declarationDescriptor instanceof PackageViewDescriptor) {
315 final PackageViewDescriptor aPackage = (PackageViewDescriptor)declarationDescriptor;
316 Collection<JetFile> files = trace.get(BindingContext.PACKAGE_TO_FILES, aPackage.getFqName());
317
318 if (files == null) {
319 return Collections.emptyList(); // package can be defined out of Kotlin sources, e. g. in library or Java code
320 }
321
322 declarations = Collections2.transform(files, new Function<JetFile, PsiElement>() {
323 @Override
324 public PsiElement apply(@Nullable JetFile file) {
325 assert file != null : "File is null for aPackage " + aPackage;
326 return file.getPackageDirective().getNameIdentifier();
327 }
328 });
329 }
330 else {
331 declarations = Collections.singletonList(BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declarationDescriptor));
332 }
333 return declarations;
334 }
335
336 public void checkRedeclarationsInInnerClassNames(@NotNull TopDownAnalysisContext c) {
337 for (ClassDescriptorWithResolutionScopes classDescriptor : c.getClasses().values()) {
338 if (classDescriptor.getKind() == ClassKind.CLASS_OBJECT) {
339 // Class objects should be considered during analysing redeclarations in classes
340 continue;
341 }
342
343 Collection<DeclarationDescriptor> allDescriptors = classDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors();
344
345 ClassDescriptorWithResolutionScopes classObj = classDescriptor.getClassObjectDescriptor();
346 if (classObj != null) {
347 Collection<DeclarationDescriptor> classObjDescriptors = classObj.getScopeForMemberLookup().getOwnDeclaredDescriptors();
348 if (!classObjDescriptors.isEmpty()) {
349 allDescriptors = Lists.newArrayList(allDescriptors);
350 allDescriptors.addAll(classObjDescriptors);
351 }
352 }
353
354 Multimap<Name, DeclarationDescriptor> descriptorMap = HashMultimap.create();
355 for (DeclarationDescriptor desc : allDescriptors) {
356 if (desc instanceof ClassDescriptor || desc instanceof PropertyDescriptor) {
357 descriptorMap.put(desc.getName(), desc);
358 }
359 }
360
361 reportRedeclarations(descriptorMap);
362 }
363 }
364
365 private void reportRedeclarations(@NotNull Multimap<Name, DeclarationDescriptor> descriptorMap) {
366 Set<Pair<PsiElement, Name>> redeclarations = Sets.newHashSet();
367 for (Name name : descriptorMap.keySet()) {
368 Collection<DeclarationDescriptor> descriptors = descriptorMap.get(name);
369 if (descriptors.size() > 1) {
370 // We mustn't compare PropertyDescriptor with PropertyDescriptor because we do this at OverloadResolver
371 for (DeclarationDescriptor descriptor : descriptors) {
372 if (descriptor instanceof ClassDescriptor) {
373 for (DeclarationDescriptor descriptor2 : descriptors) {
374 if (descriptor == descriptor2) {
375 continue;
376 }
377
378 redeclarations.add(Pair.create(
379 BindingContextUtils.classDescriptorToDeclaration(trace.getBindingContext(), (ClassDescriptor) descriptor),
380 descriptor.getName()));
381 if (descriptor2 instanceof PropertyDescriptor) {
382 redeclarations.add(Pair.create(
383 BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), descriptor2),
384 descriptor2.getName()));
385 }
386 }
387 }
388 }
389 }
390 }
391 for (Pair<PsiElement, Name> redeclaration : redeclarations) {
392 trace.report(REDECLARATION.on(redeclaration.getFirst(), redeclaration.getSecond().asString()));
393 }
394 }
395
396 public void checkRedeclarationsInPackages(@NotNull ResolveSession resolveSession, @NotNull Multimap<FqName, JetElement> topLevelFqNames) {
397 for (Map.Entry<FqName, Collection<JetElement>> entry : topLevelFqNames.asMap().entrySet()) {
398 FqName fqName = entry.getKey();
399 Collection<JetElement> declarationsOrPackageDirectives = entry.getValue();
400
401 if (fqName.isRoot()) continue;
402
403 Set<DeclarationDescriptor> descriptors = getTopLevelDescriptorsByFqName(resolveSession, fqName);
404
405 if (descriptors.size() > 1) {
406 for (JetElement declarationOrPackageDirective : declarationsOrPackageDirectives) {
407 PsiElement reportAt = declarationOrPackageDirective instanceof JetNamedDeclaration
408 ? declarationOrPackageDirective
409 : ((JetPackageDirective) declarationOrPackageDirective).getNameIdentifier();
410 trace.report(Errors.REDECLARATION.on(reportAt, fqName.shortName().asString()));
411 }
412 }
413 }
414 }
415
416 @NotNull
417 private static Set<DeclarationDescriptor> getTopLevelDescriptorsByFqName(@NotNull ResolveSession resolveSession, @NotNull FqName fqName) {
418 FqName parentFqName = fqName.parent();
419
420 Set<DeclarationDescriptor> descriptors = new HashSet<DeclarationDescriptor>();
421
422 LazyPackageDescriptor parentFragment = resolveSession.getPackageFragment(parentFqName);
423 if (parentFragment != null) {
424 // Filter out extension properties
425 descriptors.addAll(
426 KotlinPackage.filter(
427 parentFragment.getMemberScope().getProperties(fqName.shortName()),
428 new Function1<VariableDescriptor, Boolean>() {
429 @Override
430 public Boolean invoke(VariableDescriptor descriptor) {
431 return descriptor.getReceiverParameter() == null;
432 }
433 }
434 )
435 );
436 }
437
438 ContainerUtil.addIfNotNull(descriptors, resolveSession.getPackageFragment(fqName));
439
440 descriptors.addAll(resolveSession.getTopLevelClassDescriptors(fqName));
441 return descriptors;
442 }
443
444
445 }