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