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, ClassConstructorDescriptor> 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 final Map<KtTypeAlias, TypeAliasDescriptor> typeAliases = Maps.newLinkedHashMap();
049        private Map<KtCallableDeclaration, CallableMemberDescriptor> members = null;
050    
051        private final Map<KtScript, LazyScriptDescriptor> scripts = Maps.newLinkedHashMap();
052    
053        private final TopDownAnalysisMode topDownAnalysisMode;
054        private final DeclarationScopeProvider declarationScopeProvider;
055    
056        private StringBuilder debugOutput;
057    
058        public TopDownAnalysisContext(
059                @NotNull TopDownAnalysisMode topDownAnalysisMode,
060                @NotNull DataFlowInfo outerDataFlowInfo,
061                @NotNull DeclarationScopeProvider declarationScopeProvider
062        ) {
063            this.topDownAnalysisMode = topDownAnalysisMode;
064            this.outerDataFlowInfo = outerDataFlowInfo;
065            this.declarationScopeProvider = declarationScopeProvider;
066        }
067    
068        @Override
069        @NotNull
070        public TopDownAnalysisMode getTopDownAnalysisMode() {
071            return topDownAnalysisMode;
072        }
073    
074        public void debug(Object message) {
075            if (debugOutput != null) {
076                debugOutput.append(message).append("\n");
077            }
078        }
079    
080        @SuppressWarnings("UnusedDeclaration")
081        /*package*/ void enableDebugOutput() {
082            if (debugOutput == null) {
083                debugOutput = new StringBuilder();
084            }
085        }
086        
087        /*package*/ void printDebugOutput(PrintStream out) {
088            if (debugOutput != null) {
089                out.print(debugOutput);
090            }
091        }
092    
093        @Override
094        public Map<KtClassOrObject, ClassDescriptorWithResolutionScopes> getDeclaredClasses() {
095            return classes;
096        }
097    
098        @Override
099        public Map<KtAnonymousInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
100            return anonymousInitializers;
101        }
102    
103        @Override
104        public Map<KtSecondaryConstructor, ClassConstructorDescriptor> getSecondaryConstructors() {
105            return secondaryConstructors;
106        }
107    
108        @Override
109        public Collection<KtFile> getFiles() {
110            return files;
111        }
112    
113        public void addFile(@NotNull KtFile file) {
114            files.add(file);
115        }
116    
117        @Override
118        @NotNull
119        public Map<KtScript, LazyScriptDescriptor> getScripts() {
120            return scripts;
121        }
122    
123        public Map<KtParameter, PropertyDescriptor> getPrimaryConstructorParameterProperties() {
124            return primaryConstructorParameterProperties;
125        }
126    
127        @Override
128        public Map<KtProperty, PropertyDescriptor> getProperties() {
129            return properties;
130        }
131    
132        @Nullable
133        @Override
134        public LexicalScope getDeclaringScope(@NotNull KtDeclaration declaration) {
135            return declarationScopeProvider.getResolutionScopeForDeclaration(declaration);
136        }
137    
138        @Override
139        public Map<KtNamedFunction, SimpleFunctionDescriptor> getFunctions() {
140            return functions;
141        }
142    
143        @Override
144        public Map<KtTypeAlias, TypeAliasDescriptor> getTypeAliases() {
145            return typeAliases;
146        }
147    
148        @NotNull
149        public Map<KtCallableDeclaration, CallableMemberDescriptor> getMembers() {
150            if (members == null) {
151                members = Maps.newLinkedHashMap();
152                members.putAll(functions);
153                members.putAll(properties);
154                members.putAll(primaryConstructorParameterProperties);
155            }
156            return members;
157        }
158    
159        @Override
160        @NotNull
161        public DataFlowInfo getOuterDataFlowInfo() {
162            return outerDataFlowInfo;
163        }
164    
165        @NotNull
166        public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() {
167            return CollectionsKt.plus(getDeclaredClasses().values(), getScripts().values());
168        }
169    }