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.js.config;
018    
019    import com.google.common.collect.Lists;
020    import com.intellij.openapi.project.Project;
021    import com.intellij.util.SmartList;
022    import kotlin.collections.CollectionsKt;
023    import kotlin.Unit;
024    import kotlin.jvm.functions.Function1;
025    import org.jetbrains.annotations.NotNull;
026    import org.jetbrains.annotations.Nullable;
027    import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
028    import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
029    import org.jetbrains.kotlin.js.resolve.JsPlatform;
030    import org.jetbrains.kotlin.name.Name;
031    import org.jetbrains.kotlin.psi.KtFile;
032    import org.jetbrains.kotlin.resolve.TargetPlatformKt;
033    import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil;
034    import org.jetbrains.kotlin.storage.LockBasedStorageManager;
035    import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata;
036    import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils;
037    
038    import java.util.Collection;
039    import java.util.List;
040    
041    /**
042     * Base class representing a configuration of translator.
043     */
044    public abstract class Config {
045        private final boolean inlineEnabled;
046        @NotNull
047        private final Project project;
048        @NotNull
049        private final LockBasedStorageManager storageManager = new LockBasedStorageManager();
050        @NotNull
051        private final List<KtFile> sourceFilesFromLibraries = new SmartList<KtFile>();
052        @NotNull
053        private final EcmaVersion target;
054    
055        @NotNull
056        private final String moduleId;
057    
058        private final boolean sourcemap;
059        private final boolean metaInfo;
060        private final boolean kjsm;
061    
062        @NotNull
063        protected final List<KotlinJavascriptMetadata> metadata = new SmartList<KotlinJavascriptMetadata>();
064    
065        @Nullable
066        private List<ModuleDescriptorImpl> moduleDescriptors = null;
067    
068        private boolean initialized = false;
069    
070        protected Config(
071                @NotNull Project project,
072                @NotNull String moduleId,
073                @NotNull EcmaVersion ecmaVersion,
074                boolean sourcemap,
075                boolean inlineEnabled,
076                boolean metaInfo,
077                boolean kjsm
078        ) {
079            this.project = project;
080            this.target = ecmaVersion;
081            this.moduleId = moduleId;
082            this.sourcemap = sourcemap;
083            this.inlineEnabled = inlineEnabled;
084            this.metaInfo = metaInfo;
085            this.kjsm = kjsm;
086        }
087    
088        public boolean isSourcemap() {
089            return sourcemap;
090        }
091    
092        public boolean isMetaInfo() {
093            return metaInfo;
094        }
095    
096        public boolean isKjsm() {
097            return kjsm;
098        }
099    
100        public boolean isInlineEnabled() {
101            return inlineEnabled;
102        }
103    
104        @NotNull
105        public Project getProject() {
106            return project;
107        }
108    
109        @NotNull
110        public EcmaVersion getTarget() {
111            return target;
112        }
113    
114        @NotNull
115        public String getModuleId() {
116            return moduleId;
117        }
118    
119        public abstract boolean checkLibFilesAndReportErrors(@NotNull Function1<String, Unit> report);
120    
121        protected abstract void init(@NotNull List<KtFile> sourceFilesInLibraries, @NotNull List<KotlinJavascriptMetadata> metadata);
122    
123        @NotNull
124        public List<ModuleDescriptorImpl> getModuleDescriptors() {
125            init();
126            if (moduleDescriptors != null) return moduleDescriptors;
127    
128            moduleDescriptors = new SmartList<ModuleDescriptorImpl>();
129            for (KotlinJavascriptMetadata metadataEntry : metadata) {
130                moduleDescriptors.add(createModuleDescriptor(metadataEntry));
131            }
132            for (ModuleDescriptorImpl module : moduleDescriptors) {
133                setDependencies(module, moduleDescriptors);
134            }
135    
136            return moduleDescriptors;
137        }
138    
139        @NotNull
140        public List<KtFile> getSourceFilesFromLibraries() {
141            init();
142            return sourceFilesFromLibraries;
143        }
144    
145    
146        public boolean isTestConfig() {
147            return false;
148        }
149    
150        private void init() {
151            if (initialized) return;
152    
153            init(sourceFilesFromLibraries, metadata);
154            initialized = true;
155        }
156    
157        private ModuleDescriptorImpl createModuleDescriptor(KotlinJavascriptMetadata metadata) {
158            assert metadata.isAbiVersionCompatible() :
159                    "expected abi version " + KotlinJavascriptMetadataUtils.ABI_VERSION +
160                    ", but metadata.abiVersion = " + metadata.getAbiVersion();
161    
162            ModuleDescriptorImpl moduleDescriptor = TargetPlatformKt.createModule(
163                    JsPlatform.INSTANCE, Name.special("<" + metadata.getModuleName() + ">"), storageManager
164            );
165    
166            PackageFragmentProvider provider =
167                    KotlinJavascriptSerializationUtil.createPackageFragmentProvider(moduleDescriptor, metadata.getBody(), storageManager);
168    
169            moduleDescriptor.initialize(provider != null ? provider : PackageFragmentProvider.Empty.INSTANCE);
170    
171            return moduleDescriptor;
172        }
173    
174        private static void setDependencies(ModuleDescriptorImpl module, List<ModuleDescriptorImpl> modules) {
175            module.setDependencies(CollectionsKt.plus(modules, JsPlatform.INSTANCE.getBuiltIns().getBuiltInsModule()));
176        }
177    
178        @NotNull
179        public static Collection<KtFile> withJsLibAdded(@NotNull Collection<KtFile> files, @NotNull Config config) {
180            Collection<KtFile> allFiles = Lists.newArrayList();
181            allFiles.addAll(files);
182            allFiles.addAll(config.getSourceFilesFromLibraries());
183            return allFiles;
184        }
185    }