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