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.intellij.openapi.project.Project;
021    import com.intellij.psi.PsiElement;
022    import com.intellij.psi.PsiFile;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.jet.di.InjectorForTopDownAnalyzerBasic;
025    import org.jetbrains.jet.lang.ModuleConfiguration;
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.JetDeclaration;
031    import org.jetbrains.jet.lang.psi.JetFile;
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.resolve.scopes.WritableScopeImpl;
037    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingContext;
038    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
039    
040    import javax.inject.Inject;
041    import java.util.*;
042    
043    public class TopDownAnalyzer {
044    
045        @NotNull
046        private DeclarationResolver declarationResolver;
047        @NotNull
048        private TypeHierarchyResolver typeHierarchyResolver;
049        @NotNull
050        private OverrideResolver overrideResolver;
051        @NotNull
052        private OverloadResolver overloadResolver;
053        @NotNull
054        private TopDownAnalysisParameters topDownAnalysisParameters;
055        @NotNull
056        private TopDownAnalysisContext context;
057        @NotNull
058        private BindingTrace trace;
059        @NotNull
060        private ModuleDescriptor moduleDescriptor;
061        @NotNull
062        private NamespaceFactoryImpl namespaceFactory;
063        @NotNull
064        private BodyResolver bodyResolver;
065    
066        @Inject
067        public void setDeclarationResolver(@NotNull DeclarationResolver declarationResolver) {
068            this.declarationResolver = declarationResolver;
069        }
070    
071        @Inject
072        public void setTypeHierarchyResolver(@NotNull TypeHierarchyResolver typeHierarchyResolver) {
073            this.typeHierarchyResolver = typeHierarchyResolver;
074        }
075    
076        @Inject
077        public void setOverrideResolver(@NotNull OverrideResolver overrideResolver) {
078            this.overrideResolver = overrideResolver;
079        }
080    
081        @Inject
082        public void setOverloadResolver(@NotNull OverloadResolver overloadResolver) {
083            this.overloadResolver = overloadResolver;
084        }
085    
086        @Inject
087        public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) {
088            this.topDownAnalysisParameters = topDownAnalysisParameters;
089        }
090    
091        @Inject
092        public void setTrace(@NotNull BindingTrace trace) {
093            this.trace = trace;
094        }
095    
096        @Inject
097        public void setContext(@NotNull TopDownAnalysisContext context) {
098            this.context = context;
099        }
100    
101        @Inject
102        public void setModuleDescriptor(@NotNull ModuleDescriptor moduleDescriptor) {
103            this.moduleDescriptor = moduleDescriptor;
104        }
105    
106        @Inject
107        public void setNamespaceFactory(@NotNull NamespaceFactoryImpl namespaceFactory) {
108            this.namespaceFactory = namespaceFactory;
109        }
110    
111        @Inject
112        public void setBodyResolver(@NotNull BodyResolver bodyResolver) {
113            this.bodyResolver = bodyResolver;
114        }
115    
116    
117    
118        public void doProcess(
119                JetScope outerScope,
120                NamespaceLikeBuilder owner,
121                Collection<? extends PsiElement> declarations) {
122    //        context.enableDebugOutput();
123            context.debug("Enter");
124    
125            typeHierarchyResolver.process(outerScope, owner, declarations);
126            declarationResolver.process(outerScope);
127            overrideResolver.process();
128    
129            lockScopes();
130    
131            overloadResolver.process();
132    
133            if (!topDownAnalysisParameters.isAnalyzingBootstrapLibrary()) {
134                bodyResolver.resolveBodies();
135            }
136    
137            context.debug("Exit");
138            context.printDebugOutput(System.out);
139        }
140    
141        private void lockScopes() {
142            for (MutableClassDescriptor mutableClassDescriptor : context.getClasses().values()) {
143                mutableClassDescriptor.lockScopes();
144            }
145            for (MutableClassDescriptor mutableClassDescriptor : context.getObjects().values()) {
146                mutableClassDescriptor.lockScopes();
147            }
148            for (Map.Entry<JetFile, WritableScope> namespaceScope : context.getNamespaceScopes().entrySet()) {
149                // todo: this is hack in favor of REPL
150                if(!namespaceScope.getKey().isScript())
151                    namespaceScope.getValue().changeLockLevel(WritableScope.LockLevel.READING);
152            }
153        }
154    
155        public static void processStandardLibraryNamespace(
156                @NotNull Project project,
157                @NotNull BindingTrace trace,
158                @NotNull WritableScope outerScope,
159                @NotNull NamespaceDescriptorImpl standardLibraryNamespace,
160                @NotNull List<JetFile> files) {
161    
162            TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
163                    Predicates.<PsiFile>alwaysFalse(), true, false, Collections.<AnalyzerScriptParameter>emptyList());
164            InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
165                    project, topDownAnalysisParameters, new ObservableBindingTrace(trace),       
166                    KotlinBuiltIns.getInstance().getBuiltInsModule());
167    
168            injector.getTopDownAnalyzer().doProcessStandardLibraryNamespace(outerScope, standardLibraryNamespace, files);
169        }
170    
171        private void doProcessStandardLibraryNamespace(
172                WritableScope outerScope, NamespaceDescriptorImpl standardLibraryNamespace, List<JetFile> files) {
173            ArrayList<JetDeclaration> toAnalyze = new ArrayList<JetDeclaration>();
174            for(JetFile file : files) {
175                context.getNamespaceDescriptors().put(file, standardLibraryNamespace);
176                context.getNamespaceScopes().put(file, standardLibraryNamespace.getMemberScope());
177                toAnalyze.addAll(file.getDeclarations());
178            }
179    //        context.getDeclaringScopes().put(file, outerScope);
180    
181            doProcess(outerScope, standardLibraryNamespace.getBuilder(), toAnalyze);
182        }
183    
184        public static void processClassOrObject(
185                @NotNull ExpressionTypingContext context,
186                @NotNull final DeclarationDescriptor containingDeclaration,
187                @NotNull JetClassOrObject object
188        ) {
189            ModuleDescriptorImpl moduleDescriptor = new ModuleDescriptorImpl(Name.special("<dummy for object>"),
190                                                                             Collections.<ImportPath>emptyList(),
191                                                                             PlatformToKotlinClassMap.EMPTY);
192            moduleDescriptor.setModuleConfiguration(ModuleConfiguration.EMPTY);
193    
194            TopDownAnalysisParameters topDownAnalysisParameters =
195                    new TopDownAnalysisParameters(Predicates.equalTo(object.getContainingFile()),
196                    false, true, Collections.<AnalyzerScriptParameter>emptyList());
197    
198            InjectorForTopDownAnalyzerBasic injector = new InjectorForTopDownAnalyzerBasic(
199                    object.getProject(), topDownAnalysisParameters, new ObservableBindingTrace(context.trace), moduleDescriptor);
200    
201            injector.getTopDownAnalysisContext().setOuterDataFlowInfo(context.dataFlowInfo);
202    
203            injector.getTopDownAnalyzer().doProcess(context.scope, new NamespaceLikeBuilder() {
204    
205                @NotNull
206                @Override
207                public DeclarationDescriptor getOwnerForChildren() {
208                    return containingDeclaration;
209                }
210    
211                @Override
212                public void addClassifierDescriptor(@NotNull MutableClassDescriptorLite classDescriptor) {
213    
214                }
215    
216                @Override
217                public void addObjectDescriptor(@NotNull MutableClassDescriptorLite objectDescriptor) {
218    
219                }
220    
221                @Override
222                public void addFunctionDescriptor(@NotNull SimpleFunctionDescriptor functionDescriptor) {
223                    throw new UnsupportedOperationException();
224                }
225    
226                @Override
227                public void addPropertyDescriptor(@NotNull PropertyDescriptor propertyDescriptor) {
228    
229                }
230    
231                @Override
232                public ClassObjectStatus setClassObjectDescriptor(@NotNull MutableClassDescriptorLite classObjectDescriptor) {
233                    return ClassObjectStatus.NOT_ALLOWED;
234                }
235            }, Collections.<PsiElement>singletonList(object));
236        }
237    
238        public void analyzeFiles(
239                @NotNull Collection<JetFile> files,
240                @NotNull List<AnalyzerScriptParameter> scriptParameters) {
241            WritableScope scope = new WritableScopeImpl(
242                    JetScope.EMPTY, moduleDescriptor,
243                    new TraceBasedRedeclarationHandler(trace), "Root scope in analyzeNamespace");
244    
245            scope.changeLockLevel(WritableScope.LockLevel.BOTH);
246    
247            NamespaceDescriptorImpl rootNs = namespaceFactory.createNamespaceDescriptorPathIfNeeded(FqName.ROOT);
248    
249            // map "jet" namespace into KotlinBuiltIns
250            // @see DefaultModuleConfiguraiton#extendNamespaceScope
251            namespaceFactory.createNamespaceDescriptorPathIfNeeded(KotlinBuiltIns.getInstance().getBuiltInsPackageFqName());
252    
253            // Import a scope that contains all top-level namespaces that come from dependencies
254            // This makes the namespaces visible at all, does not import themselves
255            scope.importScope(rootNs.getMemberScope());
256            
257            scope.changeLockLevel(WritableScope.LockLevel.READING);
258    
259            // dummy builder is used because "root" is module descriptor,
260            // namespaces added to module explicitly in
261            doProcess(scope, new NamespaceLikeBuilderDummy(), files);
262        }
263    
264    
265        public void prepareForTheNextReplLine() {
266            context.getScriptScopes().clear();
267            context.getScripts().clear();
268        }
269    
270    
271    }
272    
273