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