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