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.lazy; 018 019 import com.google.common.base.Predicate; 020 import com.google.common.base.Predicates; 021 import com.intellij.openapi.project.Project; 022 import com.intellij.openapi.util.Computable; 023 import com.intellij.psi.PsiElement; 024 import com.intellij.psi.util.PsiTreeUtil; 025 import com.intellij.util.Function; 026 import org.jetbrains.annotations.NotNull; 027 import org.jetbrains.annotations.Nullable; 028 import org.jetbrains.jet.di.InjectorForLazyResolve; 029 import org.jetbrains.jet.lang.descriptors.*; 030 import org.jetbrains.jet.lang.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies; 031 import org.jetbrains.jet.lang.psi.*; 032 import org.jetbrains.jet.lang.resolve.BindingContext; 033 import org.jetbrains.jet.lang.resolve.BindingTrace; 034 import org.jetbrains.jet.lang.resolve.BindingTraceContext; 035 import org.jetbrains.jet.lang.resolve.DescriptorUtils; 036 import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo; 037 import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactory; 038 import org.jetbrains.jet.lang.resolve.lazy.declarations.PackageMemberDeclarationProvider; 039 import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor; 040 import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor; 041 import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager; 042 import org.jetbrains.jet.lang.resolve.name.FqName; 043 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; 044 import org.jetbrains.jet.lang.resolve.name.Name; 045 import org.jetbrains.jet.lang.resolve.scopes.JetScope; 046 047 import java.util.List; 048 049 import static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve; 050 051 public class ResolveSession implements KotlinCodeAnalyzer { 052 public static final Function<FqName, Name> NO_ALIASES = new Function<FqName, Name>() { 053 054 @Override 055 public Name fun(FqName name) { 056 return null; 057 } 058 }; 059 060 private final StorageManager storageManager; 061 062 private final ModuleDescriptor module; 063 private final LazyPackageDescriptor rootPackage; 064 065 private final BindingTrace trace; 066 private final DeclarationProviderFactory declarationProviderFactory; 067 068 private final Predicate<FqNameUnsafe> specialClasses; 069 070 071 private final InjectorForLazyResolve injector; 072 073 private final Function<FqName, Name> classifierAliases; 074 075 public ResolveSession( 076 @NotNull Project project, 077 @NotNull StorageManager storageManager, 078 @NotNull ModuleDescriptorImpl rootDescriptor, 079 @NotNull DeclarationProviderFactory declarationProviderFactory 080 ) { 081 this(project, storageManager, rootDescriptor, declarationProviderFactory, NO_ALIASES, 082 Predicates.<FqNameUnsafe>alwaysFalse(), 083 new BindingTraceContext()); 084 } 085 086 public ResolveSession( 087 @NotNull Project project, 088 @NotNull StorageManager storageManager, 089 @NotNull ModuleDescriptorImpl rootDescriptor, 090 @NotNull DeclarationProviderFactory declarationProviderFactory, 091 @NotNull BindingTrace delegationTrace 092 ) { 093 this(project, 094 storageManager, 095 rootDescriptor, 096 declarationProviderFactory, 097 NO_ALIASES, 098 Predicates.<FqNameUnsafe>alwaysFalse(), 099 delegationTrace); 100 } 101 102 @Deprecated // Internal use only 103 public ResolveSession( 104 @NotNull Project project, 105 @NotNull StorageManager storageManager, 106 @NotNull ModuleDescriptorImpl rootDescriptor, 107 @NotNull DeclarationProviderFactory declarationProviderFactory, 108 @NotNull Function<FqName, Name> classifierAliases, 109 @NotNull Predicate<FqNameUnsafe> specialClasses, 110 @NotNull BindingTrace delegationTrace 111 ) { 112 this.storageManager = storageManager; 113 this.classifierAliases = classifierAliases; 114 this.specialClasses = specialClasses; 115 this.trace = storageManager.createSafeTrace(delegationTrace); 116 this.injector = new InjectorForLazyResolve(project, this, rootDescriptor); 117 this.module = rootDescriptor; 118 PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(FqName.ROOT); 119 assert provider != null : "No declaration provider for root package in " + rootDescriptor; 120 this.rootPackage = new LazyPackageDescriptor(rootDescriptor, FqNameUnsafe.ROOT_NAME, this, provider); 121 rootDescriptor.setRootNamespace(rootPackage); 122 123 this.declarationProviderFactory = declarationProviderFactory; 124 } 125 126 @NotNull 127 public InjectorForLazyResolve getInjector() { 128 return injector; 129 } 130 131 public boolean isClassSpecial(@NotNull FqNameUnsafe fqName) { 132 return specialClasses.apply(fqName); 133 } 134 135 @Override 136 public ModuleDescriptor getRootModuleDescriptor() { 137 return module; 138 } 139 140 @NotNull 141 public StorageManager getStorageManager() { 142 return storageManager; 143 } 144 145 @Override 146 @Nullable 147 public NamespaceDescriptor getPackageDescriptor(@NotNull Name shortName) { 148 return rootPackage.getMemberScope().getNamespace(shortName); 149 } 150 151 @Override 152 @Nullable 153 public NamespaceDescriptor getPackageDescriptorByFqName(FqName fqName) { 154 if (fqName.isRoot()) { 155 return rootPackage; 156 } 157 List<Name> names = fqName.pathSegments(); 158 NamespaceDescriptor current = getPackageDescriptor(names.get(0)); 159 if (current == null) return null; 160 for (Name name : names.subList(1, names.size())) { 161 current = current.getMemberScope().getNamespace(name); 162 if (current == null) return null; 163 } 164 return current; 165 } 166 167 @Override 168 @NotNull 169 public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) { 170 if (classOrObject.getParent() instanceof JetClassObject) { 171 return getClassObjectDescriptor((JetClassObject) classOrObject.getParent()); 172 } 173 JetScope resolutionScope = getInjector().getScopeProvider().getResolutionScopeForDeclaration(classOrObject); 174 Name name = safeNameForLazyResolve(classOrObject.getNameAsName()); 175 176 // Why not use the result here. Because it may be that there is a redeclaration: 177 // class A {} class A { fun foo(): A<completion here>} 178 // and if we find the class by name only, we may b-not get the right one. 179 // This call is only needed to make sure the classes are written to trace 180 resolutionScope.getClassifier(name); 181 DeclarationDescriptor declaration = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); 182 183 if (declaration == null) { 184 // Why not use the result here. See the comment 185 resolutionScope.getObjectDescriptor(name); 186 declaration = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); 187 } 188 if (declaration == null) { 189 throw new IllegalArgumentException("Could not find a classifier for " + classOrObject + " " + classOrObject.getText()); 190 } 191 return (ClassDescriptor) declaration; 192 } 193 194 /*package*/ LazyClassDescriptor getClassObjectDescriptor(JetClassObject classObject) { 195 JetClass aClass = PsiTreeUtil.getParentOfType(classObject, JetClass.class); 196 197 final LazyClassDescriptor parentClassDescriptor; 198 199 if (aClass != null) { 200 parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(aClass); 201 } 202 else { 203 // Class object in object is an error but we want to find descriptors even for this case 204 JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(classObject, JetObjectDeclaration.class); 205 assert objectDeclaration != null : String.format("Class object %s can be in class or object in file %s", classObject, classObject.getContainingFile().getText()); 206 parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(objectDeclaration); 207 } 208 209 // Activate resolution and writing to trace 210 parentClassDescriptor.getClassObjectDescriptor(); 211 DeclarationDescriptor declaration = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classObject.getObjectDeclaration()); 212 213 if (declaration == null) { 214 // It's possible that there are several class objects and another class object is taking part in lazy resolve. We still want to 215 // build descriptors for such class objects. 216 final JetClassLikeInfo classObjectInfo = parentClassDescriptor.getClassObjectInfo(classObject); 217 if (classObjectInfo != null) { 218 final Name name = DescriptorUtils.getClassObjectName(parentClassDescriptor.getName().asString()); 219 return storageManager.compute(new Computable<LazyClassDescriptor>() { 220 @Override 221 public LazyClassDescriptor compute() { 222 // Create under lock to avoid premature access to published 'this' 223 return new LazyClassDescriptor(ResolveSession.this, parentClassDescriptor, name, classObjectInfo); 224 } 225 }); 226 } 227 } 228 229 return (LazyClassDescriptor) declaration; 230 } 231 232 @Override 233 @NotNull 234 public BindingContext getBindingContext() { 235 return trace.getBindingContext(); 236 } 237 238 @NotNull 239 public BindingTrace getTrace() { 240 return trace; 241 } 242 243 @NotNull 244 public DeclarationProviderFactory getDeclarationProviderFactory() { 245 return declarationProviderFactory; 246 } 247 248 @Override 249 @NotNull 250 public DeclarationDescriptor resolveToDescriptor(JetDeclaration declaration) { 251 DeclarationDescriptor result = declaration.accept(new JetVisitor<DeclarationDescriptor, Void>() { 252 @Override 253 public DeclarationDescriptor visitClass(JetClass klass, Void data) { 254 return getClassDescriptor(klass); 255 } 256 257 @Override 258 public DeclarationDescriptor visitObjectDeclaration(JetObjectDeclaration declaration, Void data) { 259 PsiElement parent = declaration.getParent(); 260 if (parent instanceof JetClassObject) { 261 JetClassObject jetClassObject = (JetClassObject) parent; 262 return resolveToDescriptor(jetClassObject); 263 } 264 return getClassDescriptor(declaration); 265 } 266 267 @Override 268 public DeclarationDescriptor visitClassObject(JetClassObject classObject, Void data) { 269 return getClassObjectDescriptor(classObject); 270 } 271 272 @Override 273 public DeclarationDescriptor visitTypeParameter(JetTypeParameter parameter, Void data) { 274 JetTypeParameterListOwner ownerElement = PsiTreeUtil.getParentOfType(parameter, JetTypeParameterListOwner.class); 275 DeclarationDescriptor ownerDescriptor = resolveToDescriptor(ownerElement); 276 277 List<TypeParameterDescriptor> typeParameters; 278 if (ownerDescriptor instanceof CallableDescriptor) { 279 CallableDescriptor callableDescriptor = (CallableDescriptor) ownerDescriptor; 280 typeParameters = callableDescriptor.getTypeParameters(); 281 } 282 else if (ownerDescriptor instanceof ClassDescriptor) { 283 ClassDescriptor classDescriptor = (ClassDescriptor) ownerDescriptor; 284 typeParameters = classDescriptor.getTypeConstructor().getParameters(); 285 } 286 else { 287 throw new IllegalStateException("Unknown owner kind for a type parameter: " + ownerDescriptor); 288 } 289 290 Name name = ResolveSessionUtils.safeNameForLazyResolve(parameter.getNameAsName()); 291 for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) { 292 if (typeParameterDescriptor.getName().equals(name)) { 293 return typeParameterDescriptor; 294 } 295 } 296 297 throw new IllegalStateException("Type parameter " + name + " not found for " + ownerDescriptor); 298 } 299 300 @Override 301 public DeclarationDescriptor visitNamedFunction(JetNamedFunction function, Void data) { 302 JetScope scopeForDeclaration = getInjector().getScopeProvider().getResolutionScopeForDeclaration(function); 303 scopeForDeclaration.getFunctions(safeNameForLazyResolve(function)); 304 return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, function); 305 } 306 307 @Override 308 public DeclarationDescriptor visitParameter(JetParameter parameter, Void data) { 309 PsiElement grandFather = parameter.getParent().getParent(); 310 if (grandFather instanceof JetClass) { 311 JetClass jetClass = (JetClass) grandFather; 312 // This is a primary constructor parameter 313 ClassDescriptor classDescriptor = getClassDescriptor(jetClass); 314 if (parameter.getValOrVarNode() != null) { 315 classDescriptor.getDefaultType().getMemberScope().getProperties(safeNameForLazyResolve(parameter)); 316 return getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter); 317 } 318 else { 319 ConstructorDescriptor constructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); 320 assert constructor != null: "There are constructor parameters found, so a constructor should also exist"; 321 constructor.getValueParameters(); 322 return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter); 323 } 324 } 325 return super.visitParameter(parameter, data); 326 } 327 328 @Override 329 public DeclarationDescriptor visitProperty(JetProperty property, Void data) { 330 JetScope scopeForDeclaration = getInjector().getScopeProvider().getResolutionScopeForDeclaration(property); 331 scopeForDeclaration.getProperties(safeNameForLazyResolve(property)); 332 return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property); 333 } 334 335 @Override 336 public DeclarationDescriptor visitObjectDeclarationName(JetObjectDeclarationName declarationName, Void data) { 337 JetScope scopeForDeclaration = getInjector().getScopeProvider().getResolutionScopeForDeclaration(declarationName.getParent()); 338 scopeForDeclaration.getProperties(safeNameForLazyResolve(declarationName)); 339 return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, declarationName); 340 } 341 342 @Override 343 public DeclarationDescriptor visitJetElement(JetElement element, Void data) { 344 throw new IllegalArgumentException("Unsupported declaration type: " + element + " " + 345 JetPsiUtil.getElementTextWithContext(element)); 346 } 347 }, null); 348 if (result == null) { 349 throw new IllegalStateException("No descriptor resolved for " + declaration + " " + declaration.getText()); 350 } 351 return result; 352 } 353 354 @NotNull 355 public Name resolveClassifierAlias(@NotNull FqName packageName, @NotNull Name alias) { 356 // TODO: creating a new FqName object every time... 357 Name actualName = classifierAliases.fun(packageName.child(alias)); 358 if (actualName == null) { 359 return alias; 360 } 361 return actualName; 362 } 363 364 @Override 365 public void forceResolveAll() { 366 rootPackage.acceptVoid(new DeclarationDescriptorVisitorEmptyBodies<Void, Void>() { 367 368 @Override 369 public Void visitTypeParameterDescriptor(TypeParameterDescriptor descriptor, Void data) { 370 ForceResolveUtil.forceResolveAllContents(descriptor); 371 return null; 372 } 373 374 @Override 375 public Void visitNamespaceDescriptor(NamespaceDescriptor descriptor, Void data) { 376 ForceResolveUtil.forceResolveAllContents(descriptor); 377 return null; 378 } 379 380 @Override 381 public Void visitClassDescriptor(ClassDescriptor descriptor, Void data) { 382 ForceResolveUtil.forceResolveAllContents(descriptor); 383 return null; 384 } 385 386 @Override 387 public Void visitModuleDeclaration(ModuleDescriptor descriptor, Void data) { 388 ForceResolveUtil.forceResolveAllContents(descriptor); 389 return null; 390 } 391 392 @Override 393 public Void visitScriptDescriptor(ScriptDescriptor scriptDescriptor, Void data) { 394 ForceResolveUtil.forceResolveAllContents(scriptDescriptor); 395 return null; 396 } 397 }); 398 } 399 }