001    /*
002     * Copyright 2010-2015 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.kotlin.resolve;
018    
019    import com.google.common.collect.Maps;
020    import kotlin.collections.CollectionsKt;
021    import org.jetbrains.annotations.NotNull;
022    import org.jetbrains.annotations.Nullable;
023    import org.jetbrains.kotlin.descriptors.*;
024    import org.jetbrains.kotlin.psi.*;
025    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
026    import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProvider;
027    import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyScriptDescriptor;
028    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
029    
030    import java.io.PrintStream;
031    import java.util.Collection;
032    import java.util.LinkedHashSet;
033    import java.util.Map;
034    import java.util.Set;
035    
036    public class TopDownAnalysisContext implements BodiesResolveContext {
037    
038        private final DataFlowInfo outerDataFlowInfo;
039    
040        private final Map<KtClassOrObject, ClassDescriptorWithResolutionScopes> classes = Maps.newLinkedHashMap();
041        private final Map<KtAnonymousInitializer, ClassDescriptorWithResolutionScopes> anonymousInitializers = Maps.newLinkedHashMap();
042        private final Set<KtFile> files = new LinkedHashSet<KtFile>();
043        private final Map<KtSecondaryConstructor, ConstructorDescriptor> secondaryConstructors = Maps.newLinkedHashMap();
044    
045        private final Map<KtNamedFunction, SimpleFunctionDescriptor> functions = Maps.newLinkedHashMap();
046        private final Map<KtProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap();
047        private final Map<KtParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap();
048        private Map<KtCallableDeclaration, CallableMemberDescriptor> members = null;
049    
050        private final Map<KtScript, LazyScriptDescriptor> scripts = Maps.newLinkedHashMap();
051    
052        private final TopDownAnalysisMode topDownAnalysisMode;
053        private final DeclarationScopeProvider declarationScopeProvider;
054    
055        private StringBuilder debugOutput;
056    
057        public TopDownAnalysisContext(
058                @NotNull TopDownAnalysisMode topDownAnalysisMode,
059                @NotNull DataFlowInfo outerDataFlowInfo,
060                @NotNull DeclarationScopeProvider declarationScopeProvider
061        ) {
062            this.topDownAnalysisMode = topDownAnalysisMode;
063            this.outerDataFlowInfo = outerDataFlowInfo;
064            this.declarationScopeProvider = declarationScopeProvider;
065        }
066    
067        @Override
068        @NotNull
069        public TopDownAnalysisMode getTopDownAnalysisMode() {
070            return topDownAnalysisMode;
071        }
072    
073        public void debug(Object message) {
074            if (debugOutput != null) {
075                debugOutput.append(message).append("\n");
076            }
077        }
078    
079        @SuppressWarnings("UnusedDeclaration")
080        /*package*/ void enableDebugOutput() {
081            if (debugOutput == null) {
082                debugOutput = new StringBuilder();
083            }
084        }
085        
086        /*package*/ void printDebugOutput(PrintStream out) {
087            if (debugOutput != null) {
088                out.print(debugOutput);
089            }
090        }
091    
092        @Override
093        public Map<KtClassOrObject, ClassDescriptorWithResolutionScopes> getDeclaredClasses() {
094            return classes;
095        }
096    
097        @Override
098        public Map<KtAnonymousInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
099            return anonymousInitializers;
100        }
101    
102        @Override
103        public Map<KtSecondaryConstructor, ConstructorDescriptor> getSecondaryConstructors() {
104            return secondaryConstructors;
105        }
106    
107        @Override
108        public Collection<KtFile> getFiles() {
109            return files;
110        }
111    
112        public void addFile(@NotNull KtFile file) {
113            files.add(file);
114        }
115    
116        @Override
117        @NotNull
118        public Map<KtScript, LazyScriptDescriptor> getScripts() {
119            return scripts;
120        }
121    
122        public Map<KtParameter, PropertyDescriptor> getPrimaryConstructorParameterProperties() {
123            return primaryConstructorParameterProperties;
124        }
125    
126        @Override
127        public Map<KtProperty, PropertyDescriptor> getProperties() {
128            return properties;
129        }
130    
131        @Nullable
132        @Override
133        public LexicalScope getDeclaringScope(@NotNull KtDeclaration declaration) {
134            return declarationScopeProvider.getResolutionScopeForDeclaration(declaration);
135        }
136    
137        @Override
138        public Map<KtNamedFunction, SimpleFunctionDescriptor> getFunctions() {
139            return functions;
140        }
141    
142        @NotNull
143        public Map<KtCallableDeclaration, CallableMemberDescriptor> getMembers() {
144            if (members == null) {
145                members = Maps.newLinkedHashMap();
146                members.putAll(functions);
147                members.putAll(properties);
148                members.putAll(primaryConstructorParameterProperties);
149            }
150            return members;
151        }
152    
153        @Override
154        @NotNull
155        public DataFlowInfo getOuterDataFlowInfo() {
156            return outerDataFlowInfo;
157        }
158    
159        @NotNull
160        public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() {
161            return CollectionsKt.plus(getDeclaredClasses().values(), getScripts().values());
162        }
163    }