001 /*
002 * Copyright 2010-2014 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.collect.Lists;
020 import com.intellij.openapi.project.Project;
021 import com.intellij.psi.PsiElement;
022 import com.intellij.psi.util.PsiTreeUtil;
023 import com.intellij.util.Function;
024 import com.intellij.util.containers.ContainerUtil;
025 import kotlin.Function0;
026 import org.jetbrains.annotations.NotNull;
027 import org.jetbrains.annotations.Nullable;
028 import org.jetbrains.jet.context.GlobalContextImpl;
029 import org.jetbrains.jet.lang.descriptors.*;
030 import org.jetbrains.jet.lang.psi.*;
031 import org.jetbrains.jet.lang.resolve.*;
032 import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
033 import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactory;
034 import org.jetbrains.jet.lang.resolve.lazy.declarations.PackageMemberDeclarationProvider;
035 import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor;
036 import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
037 import org.jetbrains.jet.lang.resolve.name.FqName;
038 import org.jetbrains.jet.lang.resolve.name.Name;
039 import org.jetbrains.jet.lang.resolve.name.SpecialNames;
040 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
041 import org.jetbrains.jet.renderer.DescriptorRenderer;
042 import org.jetbrains.jet.storage.ExceptionTracker;
043 import org.jetbrains.jet.storage.LazyResolveStorageManager;
044 import org.jetbrains.jet.storage.LockBasedLazyResolveStorageManager;
045 import org.jetbrains.jet.storage.MemoizedFunctionToNullable;
046
047 import javax.inject.Inject;
048 import java.util.Collection;
049 import java.util.Collections;
050 import java.util.List;
051
052 import static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve;
053
054 public class ResolveSession implements KotlinCodeAnalyzer {
055 private static final Function<FqName, Name> NO_ALIASES = new Function<FqName, Name>() {
056 @Override
057 public Name fun(FqName name) {
058 return null;
059 }
060 };
061
062 private final LazyResolveStorageManager storageManager;
063 private final ExceptionTracker exceptionTracker;
064
065 private final ModuleDescriptor module;
066
067 private final BindingTrace trace;
068 private final DeclarationProviderFactory declarationProviderFactory;
069
070 private final Function<FqName, Name> classifierAliases;
071
072 private final MemoizedFunctionToNullable<FqName, LazyPackageDescriptor> packages;
073 private final PackageFragmentProvider packageFragmentProvider;
074
075 private ScopeProvider scopeProvider;
076
077 private JetImportsFactory jetImportFactory;
078 private AnnotationResolver annotationResolve;
079 private DescriptorResolver descriptorResolver;
080 private TypeResolver typeResolver;
081 private QualifiedExpressionResolver qualifiedExpressionResolver;
082
083 @Inject
084 public void setJetImportFactory(JetImportsFactory jetImportFactory) {
085 this.jetImportFactory = jetImportFactory;
086 }
087
088 @Inject
089 public void setAnnotationResolve(AnnotationResolver annotationResolve) {
090 this.annotationResolve = annotationResolve;
091 }
092
093 @Inject
094 public void setDescriptorResolver(DescriptorResolver descriptorResolver) {
095 this.descriptorResolver = descriptorResolver;
096 }
097
098 @Inject
099 public void setTypeResolver(TypeResolver typeResolver) {
100 this.typeResolver = typeResolver;
101 }
102
103 @Inject
104 public void setQualifiedExpressionResolver(QualifiedExpressionResolver qualifiedExpressionResolver) {
105 this.qualifiedExpressionResolver = qualifiedExpressionResolver;
106 }
107
108 @Inject
109 public void setScopeProvider(ScopeProvider scopeProvider) {
110 this.scopeProvider = scopeProvider;
111 }
112
113 // Only calls from injectors expected
114 @Deprecated
115 public ResolveSession(
116 @NotNull Project project,
117 @NotNull GlobalContextImpl globalContext,
118 @NotNull ModuleDescriptorImpl rootDescriptor,
119 @NotNull DeclarationProviderFactory declarationProviderFactory,
120 @NotNull BindingTrace delegationTrace
121 ) {
122 LockBasedLazyResolveStorageManager lockBasedLazyResolveStorageManager = new LockBasedLazyResolveStorageManager(globalContext.getStorageManager());
123 this.storageManager = lockBasedLazyResolveStorageManager;
124 this.exceptionTracker = globalContext.getExceptionTracker();
125 this.trace = lockBasedLazyResolveStorageManager.createSafeTrace(delegationTrace);
126 this.module = rootDescriptor;
127
128 this.classifierAliases = NO_ALIASES;
129
130 this.packages = storageManager.createMemoizedFunctionWithNullableValues(new MemoizedFunctionToNullable<FqName, LazyPackageDescriptor>() {
131 @Nullable
132 @Override
133 public LazyPackageDescriptor invoke(FqName fqName) {
134 return createPackage(fqName);
135 }
136 });
137
138 this.declarationProviderFactory = declarationProviderFactory;
139
140 this.packageFragmentProvider = new PackageFragmentProvider() {
141 @NotNull
142 @Override
143 public List<PackageFragmentDescriptor> getPackageFragments(@NotNull FqName fqName) {
144 return ContainerUtil.<PackageFragmentDescriptor>createMaybeSingletonList(getPackageFragment(fqName));
145 }
146
147 @NotNull
148 @Override
149 public Collection<FqName> getSubPackagesOf(@NotNull FqName fqName) {
150 LazyPackageDescriptor packageDescriptor = getPackageFragment(fqName);
151 if (packageDescriptor == null) {
152 return Collections.emptyList();
153 }
154 return packageDescriptor.getDeclarationProvider().getAllDeclaredPackages();
155 }
156 };
157
158 // TODO: parameter modification
159 rootDescriptor.addFragmentProvider(DependencyKind.SOURCES, packageFragmentProvider);
160 }
161
162 @NotNull
163 public PackageFragmentProvider getPackageFragmentProvider() {
164 return packageFragmentProvider;
165 }
166
167 @Nullable
168 public LazyPackageDescriptor getPackageFragment(@NotNull FqName fqName) {
169 return packages.invoke(fqName);
170 }
171
172 @Nullable
173 private LazyPackageDescriptor createPackage(FqName fqName) {
174 if (!fqName.isRoot() && getPackageFragment(fqName.parent()) == null) {
175 return null;
176 }
177 PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName);
178 if (provider == null) {
179 return null;
180 }
181 return new LazyPackageDescriptor(module, fqName, this, provider);
182 }
183
184 @NotNull
185 @Override
186 public ModuleDescriptor getModuleDescriptor() {
187 return module;
188 }
189
190 @NotNull
191 //@Override
192 public LazyResolveStorageManager getStorageManager() {
193 return storageManager;
194 }
195
196 @NotNull
197 //@Override
198 public ExceptionTracker getExceptionTracker() {
199 return exceptionTracker;
200 }
201
202 @Override
203 @NotNull
204 public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) {
205 if (classOrObject.getParent() instanceof JetClassObject) {
206 return getClassObjectDescriptor((JetClassObject) classOrObject.getParent());
207 }
208 JetScope resolutionScope = getScopeProvider().getResolutionScopeForDeclaration(classOrObject);
209 Name name = safeNameForLazyResolve(classOrObject.getNameAsName());
210
211 // Why not use the result here. Because it may be that there is a redeclaration:
212 // class A {} class A { fun foo(): A<completion here>}
213 // and if we find the class by name only, we may b-not get the right one.
214 // This call is only needed to make sure the classes are written to trace
215 ClassifierDescriptor scopeDescriptor = resolutionScope.getClassifier(name);
216 DeclarationDescriptor descriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject);
217
218 if (descriptor == null) {
219 throw new IllegalArgumentException(
220 String.format("Could not find a classifier for %s.\n" +
221 "Found descriptor: %s (%s).\n",
222 JetPsiUtil.getElementTextWithContext(classOrObject),
223 scopeDescriptor != null ? DescriptorRenderer.DEBUG_TEXT.render(scopeDescriptor) : "null",
224 scopeDescriptor != null ? (scopeDescriptor.getContainingDeclaration().getClass()) : null));
225 }
226
227 return (ClassDescriptor) descriptor;
228 }
229
230 @NotNull
231 /*package*/ LazyClassDescriptor getClassObjectDescriptor(@NotNull JetClassObject classObject) {
232 JetClass aClass = PsiTreeUtil.getParentOfType(classObject, JetClass.class);
233
234 final LazyClassDescriptor parentClassDescriptor;
235
236 if (aClass != null) {
237 parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(aClass);
238 }
239 else {
240 // Class object in object is an error but we want to find descriptors even for this case
241 JetObjectDeclaration objectDeclaration = PsiTreeUtil.getParentOfType(classObject, JetObjectDeclaration.class);
242 assert objectDeclaration != null : String.format("Class object %s can be in class or object in file %s", classObject, classObject.getContainingFile().getText());
243 parentClassDescriptor = (LazyClassDescriptor) getClassDescriptor(objectDeclaration);
244 }
245
246 // Activate resolution and writing to trace
247 parentClassDescriptor.getClassObjectDescriptor();
248 DeclarationDescriptor declaration = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classObject.getObjectDeclaration());
249
250 if (declaration == null) {
251 // It's possible that there are several class objects and another class object is taking part in lazy resolve. We still want to
252 // build descriptors for such class objects.
253 final JetClassLikeInfo classObjectInfo = parentClassDescriptor.getClassObjectInfo(classObject);
254 assert classObjectInfo != null :
255 String.format("Failed to find class object info for existent class object declaration: %s",
256 JetPsiUtil.getElementTextWithContext(classObject));
257
258 final Name name = SpecialNames.getClassObjectName(parentClassDescriptor.getName());
259 return storageManager.compute(new Function0<LazyClassDescriptor>() {
260 @Override
261 public LazyClassDescriptor invoke() {
262 // Create under lock to avoid premature access to published 'this'
263 return new LazyClassDescriptor(ResolveSession.this, parentClassDescriptor, name, classObjectInfo);
264 }
265 });
266 }
267
268 return (LazyClassDescriptor) declaration;
269 }
270
271 @Override
272 @NotNull
273 public BindingContext getBindingContext() {
274 return trace.getBindingContext();
275 }
276
277 @NotNull
278 public BindingTrace getTrace() {
279 return trace;
280 }
281
282 @NotNull
283 public DeclarationProviderFactory getDeclarationProviderFactory() {
284 return declarationProviderFactory;
285 }
286
287 @Override
288 @NotNull
289 public DeclarationDescriptor resolveToDescriptor(JetDeclaration declaration) {
290 DeclarationDescriptor result = declaration.accept(new JetVisitor<DeclarationDescriptor, Void>() {
291 @Override
292 public DeclarationDescriptor visitClass(@NotNull JetClass klass, Void data) {
293 return getClassDescriptor(klass);
294 }
295
296 @Override
297 public DeclarationDescriptor visitObjectDeclaration(@NotNull JetObjectDeclaration declaration, Void data) {
298 PsiElement parent = declaration.getParent();
299 if (parent instanceof JetClassObject) {
300 JetClassObject jetClassObject = (JetClassObject) parent;
301 return resolveToDescriptor(jetClassObject);
302 }
303 return getClassDescriptor(declaration);
304 }
305
306 @Override
307 public DeclarationDescriptor visitClassObject(@NotNull JetClassObject classObject, Void data) {
308 return getClassObjectDescriptor(classObject);
309 }
310
311 @Override
312 public DeclarationDescriptor visitTypeParameter(@NotNull JetTypeParameter parameter, Void data) {
313 JetTypeParameterListOwner ownerElement = PsiTreeUtil.getParentOfType(parameter, JetTypeParameterListOwner.class);
314 DeclarationDescriptor ownerDescriptor = resolveToDescriptor(ownerElement);
315
316 List<TypeParameterDescriptor> typeParameters;
317 if (ownerDescriptor instanceof CallableDescriptor) {
318 CallableDescriptor callableDescriptor = (CallableDescriptor) ownerDescriptor;
319 typeParameters = callableDescriptor.getTypeParameters();
320 }
321 else if (ownerDescriptor instanceof ClassDescriptor) {
322 ClassDescriptor classDescriptor = (ClassDescriptor) ownerDescriptor;
323 typeParameters = classDescriptor.getTypeConstructor().getParameters();
324 }
325 else {
326 throw new IllegalStateException("Unknown owner kind for a type parameter: " + ownerDescriptor);
327 }
328
329 Name name = ResolveSessionUtils.safeNameForLazyResolve(parameter.getNameAsName());
330 for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
331 if (typeParameterDescriptor.getName().equals(name)) {
332 return typeParameterDescriptor;
333 }
334 }
335
336 throw new IllegalStateException("Type parameter " + name + " not found for " + ownerDescriptor);
337 }
338
339 @Override
340 public DeclarationDescriptor visitNamedFunction(@NotNull JetNamedFunction function, Void data) {
341 JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(function);
342 scopeForDeclaration.getFunctions(safeNameForLazyResolve(function));
343 return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
344 }
345
346 @Override
347 public DeclarationDescriptor visitParameter(@NotNull JetParameter parameter, Void data) {
348 PsiElement grandFather = parameter.getParent().getParent();
349 if (grandFather instanceof JetClass) {
350 JetClass jetClass = (JetClass) grandFather;
351 // This is a primary constructor parameter
352 ClassDescriptor classDescriptor = getClassDescriptor(jetClass);
353 if (parameter.getValOrVarNode() != null) {
354 classDescriptor.getDefaultType().getMemberScope().getProperties(safeNameForLazyResolve(parameter));
355 return getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
356 }
357 else {
358 ConstructorDescriptor constructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
359 assert constructor != null: "There are constructor parameters found, so a constructor should also exist";
360 constructor.getValueParameters();
361 return getBindingContext().get(BindingContext.VALUE_PARAMETER, parameter);
362 }
363 }
364 return super.visitParameter(parameter, data);
365 }
366
367 @Override
368 public DeclarationDescriptor visitProperty(@NotNull JetProperty property, Void data) {
369 JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(property);
370 scopeForDeclaration.getProperties(safeNameForLazyResolve(property));
371 return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property);
372 }
373
374 @Override
375 public DeclarationDescriptor visitJetElement(@NotNull JetElement element, Void data) {
376 throw new IllegalArgumentException("Unsupported declaration type: " + element + " " +
377 JetPsiUtil.getElementTextWithContext(element));
378 }
379 }, null);
380 if (result == null) {
381 throw new IllegalStateException("No descriptor resolved for " + declaration + " " + declaration.getText());
382 }
383 return result;
384 }
385
386 @NotNull
387 public Name resolveClassifierAlias(@NotNull FqName packageName, @NotNull Name alias) {
388 // TODO: creating a new FqName object every time...
389 Name actualName = classifierAliases.fun(packageName.child(alias));
390 if (actualName == null) {
391 return alias;
392 }
393 return actualName;
394 }
395
396 @NotNull
397 private List<LazyPackageDescriptor> getAllPackages() {
398 LazyPackageDescriptor rootPackage = getPackageFragment(FqName.ROOT);
399 assert rootPackage != null : "Root package must be initialized";
400
401 return collectAllPackages(Lists.<LazyPackageDescriptor>newArrayList(), rootPackage);
402 }
403
404 @NotNull
405 private List<LazyPackageDescriptor> collectAllPackages(
406 @NotNull List<LazyPackageDescriptor> result,
407 @NotNull LazyPackageDescriptor current
408 ) {
409 result.add(current);
410 for (FqName subPackage : packageFragmentProvider.getSubPackagesOf(current.getFqName())) {
411 LazyPackageDescriptor fragment = getPackageFragment(subPackage);
412 assert fragment != null : "Couldn't find fragment for " + subPackage;
413 collectAllPackages(result, fragment);
414 }
415 return result;
416 }
417
418 @Override
419 public void forceResolveAll() {
420 for (LazyPackageDescriptor lazyPackage : getAllPackages()) {
421 ForceResolveUtil.forceResolveAllContents(lazyPackage);
422 }
423 }
424
425 @NotNull
426 public ScopeProvider getScopeProvider() {
427 return scopeProvider;
428 }
429
430 @NotNull
431 public JetImportsFactory getJetImportsFactory() {
432 return jetImportFactory;
433 }
434
435 @NotNull
436 public AnnotationResolver getAnnotationResolver() {
437 return annotationResolve;
438 }
439
440 @NotNull
441 public DescriptorResolver getDescriptorResolver() {
442 return descriptorResolver;
443 }
444
445 @NotNull
446 public TypeResolver getTypeResolver() {
447 return typeResolver;
448 }
449
450 @NotNull
451 public QualifiedExpressionResolver getQualifiedExpressionResolver() {
452 return qualifiedExpressionResolver;
453 }
454 }