001    /*
002     * Copyright 2010-2014 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.codegen.state;
018    
019    import com.intellij.openapi.project.Project;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.jet.codegen.ClassBuilderFactory;
023    import org.jetbrains.jet.codegen.ClassBuilderMode;
024    import org.jetbrains.jet.codegen.ClassFileFactory;
025    import org.jetbrains.jet.codegen.SamWrapperClasses;
026    import org.jetbrains.jet.codegen.binding.CodegenBinding;
027    import org.jetbrains.jet.codegen.intrinsics.IntrinsicMethods;
028    import org.jetbrains.jet.lang.descriptors.ScriptDescriptor;
029    import org.jetbrains.jet.lang.psi.JetClassOrObject;
030    import org.jetbrains.jet.lang.psi.JetFile;
031    import org.jetbrains.jet.lang.resolve.BindingContext;
032    import org.jetbrains.jet.lang.resolve.BindingTrace;
033    import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
034    
035    import java.util.List;
036    
037    public class GenerationState {
038        public interface GenerateClassFilter {
039            boolean shouldProcess(JetClassOrObject classOrObject);
040    
041            GenerateClassFilter ONLY_PACKAGE_CLASS = new GenerateClassFilter() {
042                @Override
043                public boolean shouldProcess(JetClassOrObject classOrObject) {
044                    return false;
045                }
046            };
047    
048            GenerateClassFilter GENERATE_ALL = new GenerateClassFilter() {
049                @Override
050                public boolean shouldProcess(JetClassOrObject classOrObject) {
051                    return true;
052                }
053            };
054        }
055    
056        private boolean used = false;
057    
058        @NotNull
059        private final Progress progress;
060    
061        @NotNull
062        private final List<JetFile> files;
063    
064        @NotNull
065        private final ClassBuilderMode classBuilderMode;
066    
067        @NotNull
068        private final BindingContext bindingContext;
069    
070        @NotNull
071        private final ClassFileFactory classFileFactory;
072    
073        @NotNull
074        private final Project project;
075    
076        @NotNull
077        private final IntrinsicMethods intrinsics;
078    
079        @NotNull
080        private final SamWrapperClasses samWrapperClasses = new SamWrapperClasses(this);
081    
082        @NotNull
083        private final BindingTrace bindingTrace;
084    
085        @NotNull
086        private final JetTypeMapper typeMapper;
087    
088        private final boolean generateNotNullAssertions;
089    
090        private final boolean generateNotNullParamAssertions;
091    
092        private final GenerateClassFilter generateClassFilter;
093    
094        private final boolean inlineEnabled;
095    
096        @Nullable
097        private List<ScriptDescriptor> earlierScriptsForReplInterpreter;
098    
099        public GenerationState(
100                @NotNull Project project,
101                @NotNull ClassBuilderFactory builderFactory,
102                @NotNull BindingContext bindingContext,
103                @NotNull List<JetFile> files,
104                boolean inlineEnabled
105        ) {
106            this(project, builderFactory, Progress.DEAF, bindingContext, files, true, false, GenerateClassFilter.GENERATE_ALL, inlineEnabled);
107        }
108    
109        public GenerationState(
110                @NotNull Project project,
111                @NotNull ClassBuilderFactory builderFactory,
112                @NotNull Progress progress,
113                @NotNull BindingContext bindingContext,
114                @NotNull List<JetFile> files,
115                boolean generateNotNullAssertions,
116                boolean generateNotNullParamAssertions,
117                GenerateClassFilter generateClassFilter,
118                boolean inlineEnabled
119        ) {
120            this.project = project;
121            this.progress = progress;
122            this.files = files;
123            this.classBuilderMode = builderFactory.getClassBuilderMode();
124            this.inlineEnabled = inlineEnabled;
125    
126            bindingTrace = new DelegatingBindingTrace(bindingContext, "trace in GenerationState");
127            this.bindingContext = bindingTrace.getBindingContext();
128    
129            this.typeMapper = new JetTypeMapper(bindingTrace, classBuilderMode);
130    
131            this.intrinsics = new IntrinsicMethods();
132            this.classFileFactory = new ClassFileFactory(this);
133            this.classFileFactory.setBuilderFactory(builderFactory);
134    
135            this.generateNotNullAssertions = generateNotNullAssertions;
136            this.generateNotNullParamAssertions = generateNotNullParamAssertions;
137            this.generateClassFilter = generateClassFilter;
138        }
139    
140        @NotNull
141        public ClassFileFactory getFactory() {
142            return classFileFactory;
143        }
144    
145        @NotNull
146        public Progress getProgress() {
147            return progress;
148        }
149    
150        @NotNull
151        public BindingContext getBindingContext() {
152            return bindingContext;
153        }
154    
155        @NotNull
156        public ClassBuilderMode getClassBuilderMode() {
157            return classBuilderMode;
158        }
159    
160        @NotNull
161        public List<JetFile> getFiles() {
162            return files;
163        }
164    
165        @NotNull
166        public BindingTrace getBindingTrace() {
167            return bindingTrace;
168        }
169    
170        @NotNull
171        public JetTypeMapper getTypeMapper() {
172            return typeMapper;
173        }
174    
175        @NotNull
176        public Project getProject() {
177            return project;
178        }
179    
180        @NotNull
181        public IntrinsicMethods getIntrinsics() {
182            return intrinsics;
183        }
184    
185        @NotNull
186        public SamWrapperClasses getSamWrapperClasses() {
187            return samWrapperClasses;
188        }
189    
190        public boolean isGenerateNotNullAssertions() {
191            return generateNotNullAssertions;
192        }
193    
194        public boolean isGenerateNotNullParamAssertions() {
195            return generateNotNullParamAssertions;
196        }
197    
198        public GenerateClassFilter getGenerateDeclaredClassFilter() {
199            return generateClassFilter;
200        }
201    
202        public boolean isInlineEnabled() {
203            return inlineEnabled;
204        }
205    
206        public void beforeCompile() {
207            markUsed();
208    
209            //noinspection unchecked
210            CodegenBinding.initTrace(getBindingTrace(), getFiles(), getGenerateDeclaredClassFilter());
211        }
212    
213        private void markUsed() {
214            if (used) {
215                throw new IllegalStateException(GenerationState.class + " cannot be used more than once");
216            }
217            used = true;
218        }
219    
220        public void destroy() {
221        }
222    
223        @Nullable
224        public List<ScriptDescriptor> getEarlierScriptsForReplInterpreter() {
225            return earlierScriptsForReplInterpreter;
226        }
227    
228        public void setEarlierScriptsForReplInterpreter(@Nullable List<ScriptDescriptor> earlierScriptsForReplInterpreter) {
229            this.earlierScriptsForReplInterpreter = earlierScriptsForReplInterpreter;
230        }
231    }