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