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