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