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;
018
019 import com.google.common.base.Predicates;
020 import com.google.common.collect.Sets;
021 import com.intellij.psi.PsiElement;
022 import org.jetbrains.annotations.NotNull;
023 import org.jetbrains.annotations.Nullable;
024 import org.jetbrains.jet.context.GlobalContext;
025 import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic;
026 import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
027 import org.jetbrains.jet.lang.descriptors.*;
028 import org.jetbrains.jet.lang.descriptors.impl.*;
029 import org.jetbrains.jet.lang.psi.JetClassOrObject;
030 import org.jetbrains.jet.lang.psi.JetFile;
031 import org.jetbrains.jet.lang.psi.JetPsiUtil;
032 import org.jetbrains.jet.lang.resolve.name.FqName;
033 import org.jetbrains.jet.lang.resolve.name.Name;
034 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
035 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
036 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
037 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
038
039 import javax.inject.Inject;
040 import java.util.Collection;
041 import java.util.Collections;
042 import java.util.Set;
043
044 public class TopDownAnalyzer {
045
046 @NotNull
047 private DeclarationResolver declarationResolver;
048 @NotNull
049 private TypeHierarchyResolver typeHierarchyResolver;
050 @NotNull
051 private OverrideResolver overrideResolver;
052 @NotNull
053 private OverloadResolver overloadResolver;
054 @NotNull
055 private ModuleDescriptor moduleDescriptor;
056 @NotNull
057 private MutablePackageFragmentProvider packageFragmentProvider;
058 @NotNull
059 private BodyResolver bodyResolver;
060
061 @Inject
062 public void setDeclarationResolver(@NotNull DeclarationResolver declarationResolver) {
063 this.declarationResolver = declarationResolver;
064 }
065
066 @Inject
067 public void setTypeHierarchyResolver(@NotNull TypeHierarchyResolver typeHierarchyResolver) {
068 this.typeHierarchyResolver = typeHierarchyResolver;
069 }
070
071 @Inject
072 public void setOverrideResolver(@NotNull OverrideResolver overrideResolver) {
073 this.overrideResolver = overrideResolver;
074 }
075
076 @Inject
077 public void setOverloadResolver(@NotNull OverloadResolver overloadResolver) {
078 this.overloadResolver = overloadResolver;
079 }
080
081 @Inject
082 public void setModuleDescriptor(@NotNull ModuleDescriptor moduleDescriptor) {
083 this.moduleDescriptor = moduleDescriptor;
084 }
085
086 @Inject
087 public void setPackageFragmentProvider(@NotNull MutablePackageFragmentProvider packageFragmentProvider) {
088 this.packageFragmentProvider = packageFragmentProvider;
089 }
090
091 @Inject
092 public void setBodyResolver(@NotNull BodyResolver bodyResolver) {
093 this.bodyResolver = bodyResolver;
094 }
095
096 public void doProcess(
097 @NotNull TopDownAnalysisContext c,
098 @NotNull JetScope outerScope,
099 @NotNull PackageLikeBuilder owner,
100 @NotNull Collection<? extends PsiElement> declarations
101 ) {
102 // c.enableDebugOutput();
103 c.debug("Enter");
104
105 typeHierarchyResolver.process(c, outerScope, owner, declarations);
106 declarationResolver.process(c);
107 overrideResolver.process(c);
108
109 lockScopes(c);
110
111 overloadResolver.process(c);
112
113 if (!c.getTopDownAnalysisParameters().isAnalyzingBootstrapLibrary()) {
114 bodyResolver.resolveBodies(c);
115 }
116
117 c.debug("Exit");
118 c.printDebugOutput(System.out);
119 }
120
121 private void lockScopes(@NotNull TopDownAnalysisContext c) {
122 for (ClassDescriptorWithResolutionScopes mutableClassDescriptor : c.getClasses().values()) {
123 ((MutableClassDescriptor) mutableClassDescriptor).lockScopes();
124 }
125 Set<FqName> scriptFqNames = Sets.newHashSet();
126 for (JetFile file : c.getFileScopes().keySet()) {
127 if (file.isScript()) {
128 scriptFqNames.add(JetPsiUtil.getFQName(file));
129 }
130 }
131 for (MutablePackageFragmentDescriptor fragment : packageFragmentProvider.getAllFragments()) {
132 // todo: this is hack in favor of REPL
133 if (!scriptFqNames.contains(fragment.getFqName())) {
134 fragment.getMemberScope().changeLockLevel(WritableScope.LockLevel.READING);
135 }
136 }
137 }
138
139 public static void processClassOrObject(
140 @NotNull GlobalContext globalContext,
141 @Nullable final WritableScope scope,
142 @NotNull ExpressionTypingContext context,
143 @NotNull final DeclarationDescriptor containingDeclaration,
144 @NotNull JetClassOrObject object
145 ) {
146 ModuleDescriptorImpl moduleDescriptor = new ModuleDescriptorImpl(Name.special("<dummy for object>"),
147 Collections.<ImportPath>emptyList(),
148 PlatformToKotlinClassMap.EMPTY);
149
150 TopDownAnalysisParameters topDownAnalysisParameters =
151 new TopDownAnalysisParameters(
152 globalContext.getStorageManager(),
153 globalContext.getExceptionTracker(),
154 Predicates.equalTo(object.getContainingFile()),
155 false,
156 true,
157 Collections.<AnalyzerScriptParameter>emptyList()
158 );
159
160 InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
161 object.getProject(), topDownAnalysisParameters, context.trace, moduleDescriptor
162 );
163
164 TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters);
165 c.setOuterDataFlowInfo(context.dataFlowInfo);
166
167 injector.getTopDownAnalyzer().doProcess(
168 c,
169 context.scope,
170 new PackageLikeBuilder() {
171
172 @NotNull
173 @Override
174 public DeclarationDescriptor getOwnerForChildren() {
175 return containingDeclaration;
176 }
177
178 @Override
179 public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
180 if (scope != null) {
181 scope.addClassifierDescriptor(classDescriptor);
182 }
183 }
184
185 @Override
186 public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
187 throw new UnsupportedOperationException();
188 }
189
190 @Override
191 public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
192
193 }
194
195 @Override
196 public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) {
197 return ClassObjectStatus.NOT_ALLOWED;
198 }
199 },
200 Collections.<PsiElement>singletonList(object)
201 );
202 }
203
204 @NotNull
205 public TopDownAnalysisContext analyzeFiles(
206 @NotNull TopDownAnalysisParameters topDownAnalysisParameters,
207 @NotNull Collection<JetFile> files
208 ) {
209 ((ModuleDescriptorImpl) moduleDescriptor).addFragmentProvider(DependencyKind.SOURCES, packageFragmentProvider);
210
211 // "depend on" builtins module
212 ((ModuleDescriptorImpl) moduleDescriptor).addFragmentProvider(DependencyKind.BUILT_INS, KotlinBuiltIns.getInstance().getBuiltInsModule().getPackageFragmentProvider());
213
214 // dummy builder is used because "root" is module descriptor,
215 // packages added to module explicitly in
216
217 TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters);
218 doProcess(c, JetModuleUtil.getSubpackagesOfRootScope(moduleDescriptor), new PackageLikeBuilderDummy(), files);
219 return c;
220 }
221
222
223 public void prepareForTheNextReplLine(@NotNull TopDownAnalysisContext c) {
224 c.getScriptScopes().clear();
225 c.getScripts().clear();
226 }
227
228
229 @NotNull
230 public MutablePackageFragmentProvider getPackageFragmentProvider() {
231 return packageFragmentProvider;
232 }
233 }
234
235