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