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 }