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