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.base.Function;
020    import com.google.common.base.Functions;
021    import com.google.common.collect.Maps;
022    import kotlin.KotlinPackage;
023    import kotlin.jvm.functions.Function1;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.kotlin.descriptors.*;
026    import org.jetbrains.kotlin.psi.*;
027    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
028    import org.jetbrains.kotlin.resolve.scopes.JetScope;
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<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes = Maps.newLinkedHashMap();
041        private final Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> anonymousInitializers = Maps.newLinkedHashMap();
042        private final Set<JetFile> files = new LinkedHashSet<JetFile>();
043        private final Map<JetSecondaryConstructor, ConstructorDescriptor> secondaryConstructors = Maps.newLinkedHashMap();
044    
045        private final Map<JetDeclaration, JetScope> declaringScopes = Maps.newHashMap();
046        private final Map<JetNamedFunction, SimpleFunctionDescriptor> functions = Maps.newLinkedHashMap();
047        private final Map<JetProperty, PropertyDescriptor> properties = Maps.newLinkedHashMap();
048        private final Map<JetParameter, PropertyDescriptor> primaryConstructorParameterProperties = Maps.newHashMap();
049        private Map<JetCallableDeclaration, CallableMemberDescriptor> members = null;
050    
051        private final Map<JetScript, ScriptDescriptor> scripts = Maps.newLinkedHashMap();
052    
053        private final TopDownAnalysisMode topDownAnalysisMode;
054    
055        private StringBuilder debugOutput;
056    
057        public TopDownAnalysisContext(@NotNull TopDownAnalysisMode topDownAnalysisMode, @NotNull DataFlowInfo outerDataFlowInfo) {
058            this.topDownAnalysisMode = topDownAnalysisMode;
059            this.outerDataFlowInfo = outerDataFlowInfo;
060        }
061    
062        @Override
063        @NotNull
064        public TopDownAnalysisMode getTopDownAnalysisMode() {
065            return topDownAnalysisMode;
066        }
067    
068        public void debug(Object message) {
069            if (debugOutput != null) {
070                debugOutput.append(message).append("\n");
071            }
072        }
073    
074        @SuppressWarnings("UnusedDeclaration")
075        /*package*/ void enableDebugOutput() {
076            if (debugOutput == null) {
077                debugOutput = new StringBuilder();
078            }
079        }
080        
081        /*package*/ void printDebugOutput(PrintStream out) {
082            if (debugOutput != null) {
083                out.print(debugOutput);
084            }
085        }
086    
087        @Override
088        public Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> getDeclaredClasses() {
089            return classes;
090        }
091    
092        @Override
093        public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
094            return anonymousInitializers;
095        }
096    
097        @Override
098        public Map<JetSecondaryConstructor, ConstructorDescriptor> getSecondaryConstructors() {
099            return secondaryConstructors;
100        }
101    
102        @Override
103        public Collection<JetFile> getFiles() {
104            return files;
105        }
106    
107        public void addFile(@NotNull JetFile file) {
108            files.add(file);
109        }
110    
111        @Override
112        @NotNull
113        public Map<JetScript, ScriptDescriptor> getScripts() {
114            return scripts;
115        }
116    
117        public Map<JetParameter, PropertyDescriptor> getPrimaryConstructorParameterProperties() {
118            return primaryConstructorParameterProperties;
119        }
120    
121        @Override
122        public Map<JetProperty, PropertyDescriptor> getProperties() {
123            return properties;
124        }
125    
126        @Override
127        public Function<JetDeclaration, JetScope> getDeclaringScopes() {
128            return Functions.forMap(declaringScopes);
129        }
130    
131        public void registerDeclaringScope(@NotNull JetDeclaration declaration, @NotNull JetScope scope) {
132            declaringScopes.put(declaration, scope);
133        }
134    
135        @Override
136        public Map<JetNamedFunction, SimpleFunctionDescriptor> getFunctions() {
137            return functions;
138        }
139    
140        @NotNull
141        public Map<JetCallableDeclaration, CallableMemberDescriptor> getMembers() {
142            if (members == null) {
143                members = Maps.newLinkedHashMap();
144                members.putAll(functions);
145                members.putAll(properties);
146                members.putAll(primaryConstructorParameterProperties);
147            }
148            return members;
149        }
150    
151        @Override
152        @NotNull
153        public DataFlowInfo getOuterDataFlowInfo() {
154            return outerDataFlowInfo;
155        }
156    
157        @NotNull
158        public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() {
159            // SCRIPT: all classes are declared classes + script classes
160            Collection<ClassDescriptorWithResolutionScopes> scriptClasses = KotlinPackage.map(
161                    getScripts().values(),
162                    new Function1<ScriptDescriptor, ClassDescriptorWithResolutionScopes>() {
163                        @Override
164                        public ClassDescriptorWithResolutionScopes invoke(ScriptDescriptor scriptDescriptor) {
165                            return (ClassDescriptorWithResolutionScopes) scriptDescriptor.getClassDescriptor();
166                        }
167                    }
168            );
169            return KotlinPackage.plus(getDeclaredClasses().values(), scriptClasses);
170        }
171    }