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 017package org.jetbrains.jet.lang.resolve; 018 019import com.google.common.base.Function; 020import com.google.common.base.Predicate; 021import com.google.common.collect.*; 022import com.intellij.openapi.util.Pair; 023import com.intellij.psi.PsiElement; 024import org.jetbrains.annotations.NotNull; 025import org.jetbrains.annotations.Nullable; 026import org.jetbrains.jet.lang.descriptors.*; 027import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor; 028import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptorLite; 029import org.jetbrains.jet.lang.descriptors.impl.NamespaceDescriptorImpl; 030import org.jetbrains.jet.lang.descriptors.impl.NamespaceLikeBuilder; 031import org.jetbrains.jet.lang.psi.*; 032import org.jetbrains.jet.lang.resolve.name.Name; 033import org.jetbrains.jet.lang.resolve.scopes.JetScope; 034import org.jetbrains.jet.lang.resolve.scopes.WritableScope; 035import org.jetbrains.jet.lang.types.ErrorUtils; 036import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; 037import org.jetbrains.jet.renderer.DescriptorRenderer; 038 039import javax.inject.Inject; 040import java.util.*; 041 042import static org.jetbrains.jet.lang.diagnostics.Errors.*; 043 044public 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(@NotNull List<JetDeclaration> declarations, 183 final @NotNull JetScope scopeForFunctions, 184 final @NotNull JetScope scopeForPropertyInitializers, final @NotNull JetScope scopeForPropertyAccessors, 185 final @NotNull NamespaceLikeBuilder namespaceLike) 186 { 187 for (JetDeclaration declaration : declarations) { 188 declaration.accept(new JetVisitorVoid() { 189 @Override 190 public void visitNamedFunction(JetNamedFunction function) { 191 SimpleFunctionDescriptor functionDescriptor = descriptorResolver.resolveFunctionDescriptor(namespaceLike.getOwnerForChildren(), scopeForFunctions, function, trace); 192 namespaceLike.addFunctionDescriptor(functionDescriptor); 193 context.getFunctions().put(function, functionDescriptor); 194 context.registerDeclaringScope(function, scopeForFunctions); 195 } 196 197 @Override 198 public void visitProperty(JetProperty property) { 199 PropertyDescriptor propertyDescriptor = descriptorResolver.resolvePropertyDescriptor(namespaceLike.getOwnerForChildren(), scopeForPropertyInitializers, property, trace); 200 namespaceLike.addPropertyDescriptor(propertyDescriptor); 201 context.getProperties().put(property, propertyDescriptor); 202 context.registerDeclaringScope(property, scopeForPropertyInitializers); 203 JetPropertyAccessor getter = property.getGetter(); 204 if (getter != null) { 205 context.registerDeclaringScope(getter, scopeForPropertyAccessors); 206 } 207 JetPropertyAccessor setter = property.getSetter(); 208 if (setter != null) { 209 context.registerDeclaringScope(setter, scopeForPropertyAccessors); 210 } 211 } 212 213 @Override 214 public void visitObjectDeclaration(JetObjectDeclaration declaration) { 215 PropertyDescriptor propertyDescriptor = descriptorResolver.resolveObjectDeclarationAsPropertyDescriptor( 216 namespaceLike.getOwnerForChildren(), declaration, context.getObjects().get(declaration), trace); 217 218 namespaceLike.addPropertyDescriptor(propertyDescriptor); 219 } 220 221 @Override 222 public void visitEnumEntry(JetEnumEntry enumEntry) { 223 // FIX: Bad cast 224 MutableClassDescriptorLite classObjectDescriptor = 225 ((MutableClassDescriptorLite)namespaceLike.getOwnerForChildren()).getClassObjectDescriptor(); 226 assert classObjectDescriptor != null; 227 PropertyDescriptor propertyDescriptor = descriptorResolver.resolveObjectDeclarationAsPropertyDescriptor( 228 classObjectDescriptor, enumEntry, context.getClasses().get(enumEntry), trace); 229 classObjectDescriptor.getBuilder().addPropertyDescriptor(propertyDescriptor); 230 } 231 }); 232 } 233 } 234 235 private void createFunctionsForDataClasses() { 236 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) { 237 JetClass jetClass = entry.getKey(); 238 MutableClassDescriptor classDescriptor = entry.getValue(); 239 240 if (jetClass.hasPrimaryConstructor() && KotlinBuiltIns.getInstance().isData(classDescriptor)) { 241 ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(classDescriptor); 242 createComponentFunctions(classDescriptor, constructor); 243 createCopyFunction(classDescriptor, constructor); 244 } 245 } 246 } 247 248 private void createComponentFunctions(@NotNull MutableClassDescriptor classDescriptor, @NotNull ConstructorDescriptor constructorDescriptor) { 249 int parameterIndex = 0; 250 for (ValueParameterDescriptor parameter : constructorDescriptor.getValueParameters()) { 251 if (!ErrorUtils.isErrorType(parameter.getType())) { 252 PropertyDescriptor property = trace.get(BindingContext.VALUE_PARAMETER_AS_PROPERTY, parameter); 253 if (property != null) { 254 ++parameterIndex; 255 256 SimpleFunctionDescriptor functionDescriptor = 257 DescriptorResolver.createComponentFunctionDescriptor(parameterIndex, property, parameter, classDescriptor, trace); 258 259 classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor); 260 } 261 } 262 } 263 } 264 265 private void createCopyFunction(@NotNull MutableClassDescriptor classDescriptor, @NotNull ConstructorDescriptor constructorDescriptor) { 266 SimpleFunctionDescriptor functionDescriptor = DescriptorResolver.createCopyFunctionDescriptor( 267 constructorDescriptor.getValueParameters(), classDescriptor, trace); 268 269 classDescriptor.getBuilder().addFunctionDescriptor(functionDescriptor); 270 } 271 272 private void processPrimaryConstructor(MutableClassDescriptor classDescriptor, JetClass klass) { 273 if (classDescriptor.getKind() == ClassKind.TRAIT) { 274 JetParameterList primaryConstructorParameterList = klass.getPrimaryConstructorParameterList(); 275 if (primaryConstructorParameterList != null) { 276 trace.report(CONSTRUCTOR_IN_TRAIT.on(primaryConstructorParameterList)); 277 } 278 } 279 280 // TODO : not all the parameters are real properties 281 JetScope memberScope = classDescriptor.getScopeForSupertypeResolution(); 282 ConstructorDescriptor constructorDescriptor = descriptorResolver.resolvePrimaryConstructorDescriptor(memberScope, classDescriptor, klass, trace); 283 if (constructorDescriptor != null) { 284 List<ValueParameterDescriptor> valueParameterDescriptors = constructorDescriptor.getValueParameters(); 285 List<JetParameter> primaryConstructorParameters = klass.getPrimaryConstructorParameters(); 286 assert valueParameterDescriptors.size() == primaryConstructorParameters.size(); 287 for (ValueParameterDescriptor valueParameterDescriptor : valueParameterDescriptors) { 288 JetParameter parameter = primaryConstructorParameters.get(valueParameterDescriptor.getIndex()); 289 if (parameter.getValOrVarNode() != null) { 290 PropertyDescriptor propertyDescriptor = descriptorResolver.resolvePrimaryConstructorParameterToAProperty( 291 classDescriptor, 292 valueParameterDescriptor, 293 memberScope, 294 parameter, trace 295 ); 296 classDescriptor.getBuilder().addPropertyDescriptor(propertyDescriptor); 297 context.getPrimaryConstructorParameterProperties().put(parameter, propertyDescriptor); 298 } 299 } 300 if (classDescriptor.getKind() != ClassKind.TRAIT) { 301 classDescriptor.setPrimaryConstructor(constructorDescriptor, trace); 302 } 303 } 304 } 305 306 private void checkRedeclarationsInNamespaces() { 307 for (NamespaceDescriptorImpl descriptor : context.getNamespaceDescriptors().values()) { 308 Multimap<Name, DeclarationDescriptor> simpleNameDescriptors = descriptor.getMemberScope().getDeclaredDescriptorsAccessibleBySimpleName(); 309 for (Name name : simpleNameDescriptors.keySet()) { 310 // Keep only properties with no receiver 311 Collection<DeclarationDescriptor> descriptors = Collections2.filter(simpleNameDescriptors.get(name), new Predicate<DeclarationDescriptor>() { 312 @Override 313 public boolean apply(@Nullable DeclarationDescriptor descriptor) { 314 if (descriptor instanceof PropertyDescriptor) { 315 PropertyDescriptor propertyDescriptor = (PropertyDescriptor)descriptor; 316 return propertyDescriptor.getReceiverParameter() == null; 317 } 318 return true; 319 } 320 }); 321 if (descriptors.size() > 1) { 322 for (DeclarationDescriptor declarationDescriptor : descriptors) { 323 for (PsiElement declaration : getDeclarationsByDescriptor(declarationDescriptor)) { 324 assert declaration != null : "Null declaration for descriptor: " + declarationDescriptor + " " + 325 (declarationDescriptor != null ? DescriptorRenderer.TEXT.render(declarationDescriptor) : ""); 326 trace.report(REDECLARATION.on(declaration, declarationDescriptor.getName().asString())); 327 } 328 } 329 } 330 } 331 } 332 } 333 334 private Collection<PsiElement> getDeclarationsByDescriptor(DeclarationDescriptor declarationDescriptor) { 335 Collection<PsiElement> declarations; 336 if (declarationDescriptor instanceof NamespaceDescriptor) { 337 final NamespaceDescriptor namespace = (NamespaceDescriptor)declarationDescriptor; 338 Collection<JetFile> files = trace.get(BindingContext.NAMESPACE_TO_FILES, namespace); 339 340 if (files == null) { 341 throw new IllegalStateException("declarations corresponding to " + namespace + " are not found"); 342 } 343 344 declarations = Collections2.transform(files, new Function<JetFile, PsiElement>() { 345 @Override 346 public PsiElement apply(@Nullable JetFile file) { 347 assert file != null : "File is null for namespace " + namespace; 348 return file.getNamespaceHeader().getNameIdentifier(); 349 } 350 }); 351 } 352 else { 353 declarations = Collections.singletonList(BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declarationDescriptor)); 354 } 355 return declarations; 356 } 357 358 private void checkRedeclarationsInInnerClassNames() { 359 Iterable<MutableClassDescriptor> classesAndObjects = Iterables.concat(context.getClasses().values(), context.getObjects().values()); 360 for (MutableClassDescriptor classDescriptor : classesAndObjects) { 361 if (classDescriptor.getKind() == ClassKind.CLASS_OBJECT) { 362 // Class objects should be considered during analysing redeclarations in classes 363 continue; 364 } 365 366 Collection<DeclarationDescriptor> allDescriptors = classDescriptor.getScopeForMemberLookup().getOwnDeclaredDescriptors(); 367 368 MutableClassDescriptorLite classObj = classDescriptor.getClassObjectDescriptor(); 369 if (classObj != null) { 370 Collection<DeclarationDescriptor> classObjDescriptors = classObj.getScopeForMemberLookup().getOwnDeclaredDescriptors(); 371 if (!classObjDescriptors.isEmpty()) { 372 allDescriptors = Lists.newArrayList(allDescriptors); 373 allDescriptors.addAll(classObjDescriptors); 374 } 375 } 376 377 Multimap<Name, DeclarationDescriptor> descriptorMap = HashMultimap.create(); 378 for (DeclarationDescriptor desc : allDescriptors) { 379 if (desc instanceof ClassDescriptor || desc instanceof PropertyDescriptor) { 380 descriptorMap.put(desc.getName(), desc); 381 } 382 } 383 384 reportRedeclarations(descriptorMap); 385 } 386 } 387 388 private void reportRedeclarations(@NotNull Multimap<Name, DeclarationDescriptor> descriptorMap) { 389 Set<Pair<PsiElement, Name>> redeclarations = Sets.newHashSet(); 390 for (Name name : descriptorMap.keySet()) { 391 Collection<DeclarationDescriptor> descriptors = descriptorMap.get(name); 392 if (descriptors.size() > 1) { 393 // We mustn't compare PropertyDescriptor with PropertyDescriptor because we do this at OverloadResolver 394 for (DeclarationDescriptor descriptor : descriptors) { 395 if (descriptor instanceof ClassDescriptor) { 396 for (DeclarationDescriptor descriptor2 : descriptors) { 397 if (descriptor == descriptor2) { 398 continue; 399 } 400 401 redeclarations.add(Pair.create( 402 BindingContextUtils.classDescriptorToDeclaration(trace.getBindingContext(), (ClassDescriptor) descriptor), 403 descriptor.getName())); 404 if (descriptor2 instanceof PropertyDescriptor) { 405 redeclarations.add(Pair.create( 406 BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), descriptor2), 407 descriptor2.getName())); 408 } 409 } 410 } 411 } 412 } 413 } 414 for (Pair<PsiElement, Name> redeclaration : redeclarations) { 415 trace.report(REDECLARATION.on(redeclaration.getFirst(), redeclaration.getSecond().asString())); 416 } 417 } 418 419 420}