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