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            this.intrinsics.init();
135    
136            this.generateNotNullAssertions = generateNotNullAssertions;
137            this.generateNotNullParamAssertions = generateNotNullParamAssertions;
138            this.generateClassFilter = generateClassFilter;
139        }
140    
141        @NotNull
142        public ClassFileFactory getFactory() {
143            return classFileFactory;
144        }
145    
146        @NotNull
147        public Progress getProgress() {
148            return progress;
149        }
150    
151        @NotNull
152        public BindingContext getBindingContext() {
153            return bindingContext;
154        }
155    
156        @NotNull
157        public ClassBuilderMode getClassBuilderMode() {
158            return classBuilderMode;
159        }
160    
161        @NotNull
162        public List<JetFile> getFiles() {
163            return files;
164        }
165    
166        @NotNull
167        public BindingTrace getBindingTrace() {
168            return bindingTrace;
169        }
170    
171        @NotNull
172        public JetTypeMapper getTypeMapper() {
173            return typeMapper;
174        }
175    
176        @NotNull
177        public Project getProject() {
178            return project;
179        }
180    
181        @NotNull
182        public IntrinsicMethods getIntrinsics() {
183            return intrinsics;
184        }
185    
186        @NotNull
187        public SamWrapperClasses getSamWrapperClasses() {
188            return samWrapperClasses;
189        }
190    
191        public boolean isGenerateNotNullAssertions() {
192            return generateNotNullAssertions;
193        }
194    
195        public boolean isGenerateNotNullParamAssertions() {
196            return generateNotNullParamAssertions;
197        }
198    
199        public GenerateClassFilter getGenerateDeclaredClassFilter() {
200            return generateClassFilter;
201        }
202    
203        public boolean isInlineEnabled() {
204            return inlineEnabled;
205        }
206    
207        public void beforeCompile() {
208            markUsed();
209    
210            //noinspection unchecked
211            CodegenBinding.initTrace(getBindingTrace(), getFiles(), getGenerateDeclaredClassFilter());
212        }
213    
214        private void markUsed() {
215            if (used) {
216                throw new IllegalStateException(GenerationState.class + " cannot be used more than once");
217            }
218            used = true;
219        }
220    
221        public void destroy() {
222        }
223    
224        @Nullable
225        public List<ScriptDescriptor> getEarlierScriptsForReplInterpreter() {
226            return earlierScriptsForReplInterpreter;
227        }
228    
229        public void setEarlierScriptsForReplInterpreter(@Nullable List<ScriptDescriptor> earlierScriptsForReplInterpreter) {
230            this.earlierScriptsForReplInterpreter = earlierScriptsForReplInterpreter;
231        }
232    }