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.psi.PsiElement;
023 import com.intellij.psi.util.PsiTreeUtil;
024 import com.intellij.util.Function;
025 import org.jetbrains.annotations.NotNull;
026 import org.jetbrains.annotations.Nullable;
027 import org.jetbrains.jet.di.InjectorForLazyResolve;
028 import org.jetbrains.jet.lang.descriptors.*;
029 import org.jetbrains.jet.lang.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies;
030 import org.jetbrains.jet.lang.psi.*;
031 import org.jetbrains.jet.lang.resolve.BindingContext;
032 import org.jetbrains.jet.lang.resolve.BindingTrace;
033 import org.jetbrains.jet.lang.resolve.BindingTraceContext;
034 import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactory;
035 import org.jetbrains.jet.lang.resolve.lazy.declarations.PackageMemberDeclarationProvider;
036 import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor;
037 import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyPackageDescriptor;
038 import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
039 import org.jetbrains.jet.lang.resolve.name.FqName;
040 import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
041 import org.jetbrains.jet.lang.resolve.name.Name;
042 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
043
044 import java.util.List;
045
046 import static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve;
047
048 public 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 }