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.KotlinPackage;
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.builtins.KotlinBuiltIns;
028    import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
029    import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
030    import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS;
031    import org.jetbrains.kotlin.name.Name;
032    import org.jetbrains.kotlin.psi.JetFile;
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<JetFile> sourceFilesFromLibraries = new SmartList<JetFile>();
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    
061        @NotNull
062        protected final List<KotlinJavascriptMetadata> metadata = new SmartList<KotlinJavascriptMetadata>();
063    
064        @Nullable
065        private List<ModuleDescriptorImpl> moduleDescriptors = null;
066    
067        private boolean initialized = false;
068    
069        protected Config(
070                @NotNull Project project,
071                @NotNull String moduleId,
072                @NotNull EcmaVersion ecmaVersion,
073                boolean sourcemap,
074                boolean inlineEnabled,
075                boolean metaInfo
076        ) {
077            this.project = project;
078            this.target = ecmaVersion;
079            this.moduleId = moduleId;
080            this.sourcemap = sourcemap;
081            this.inlineEnabled = inlineEnabled;
082            this.metaInfo = metaInfo;
083        }
084    
085        public boolean isSourcemap() {
086            return sourcemap;
087        }
088    
089        public boolean isMetaInfo() {
090            return metaInfo;
091        }
092    
093        public boolean isInlineEnabled() {
094            return inlineEnabled;
095        }
096    
097        @NotNull
098        public Project getProject() {
099            return project;
100        }
101    
102        @NotNull
103        public EcmaVersion getTarget() {
104            return target;
105        }
106    
107        @NotNull
108        public String getModuleId() {
109            return moduleId;
110        }
111    
112        public abstract boolean checkLibFilesAndReportErrors(@NotNull Function1<String, Unit> report);
113    
114        protected abstract void init(@NotNull List<JetFile> sourceFilesInLibraries, @NotNull List<KotlinJavascriptMetadata> metadata);
115    
116        @NotNull
117        public List<ModuleDescriptorImpl> getModuleDescriptors() {
118            init();
119            if (moduleDescriptors != null) return moduleDescriptors;
120    
121            moduleDescriptors = new SmartList<ModuleDescriptorImpl>();
122            for (KotlinJavascriptMetadata metadataEntry : metadata) {
123                moduleDescriptors.add(createModuleDescriptor(metadataEntry));
124            }
125            for (ModuleDescriptorImpl module : moduleDescriptors) {
126                setDependencies(module, moduleDescriptors);
127            }
128    
129            return moduleDescriptors;
130        }
131    
132        @NotNull
133        public List<JetFile> getSourceFilesFromLibraries() {
134            init();
135            return sourceFilesFromLibraries;
136        }
137    
138    
139        public boolean isTestConfig() {
140            return false;
141        }
142    
143        private void init() {
144            if (initialized) return;
145    
146            init(sourceFilesFromLibraries, metadata);
147            initialized = true;
148        }
149    
150        private ModuleDescriptorImpl createModuleDescriptor(KotlinJavascriptMetadata metadata) {
151            assert metadata.getIsAbiVersionCompatible() :
152                    "expected abi version " + KotlinJavascriptMetadataUtils.ABI_VERSION + ", but metadata.abiVersion = " + metadata.getAbiVersion();
153    
154            ModuleDescriptorImpl moduleDescriptor = new ModuleDescriptorImpl(
155                    Name.special("<" + metadata.getModuleName() + ">"), storageManager,
156                    TopDownAnalyzerFacadeForJS.JS_MODULE_PARAMETERS
157            );
158    
159            PackageFragmentProvider provider =
160                    KotlinJavascriptSerializationUtil.createPackageFragmentProvider(moduleDescriptor, metadata.getBody(), storageManager);
161    
162            moduleDescriptor.initialize(provider != null ? provider : PackageFragmentProvider.Empty.INSTANCE$);
163    
164            return moduleDescriptor;
165        }
166    
167        private static void setDependencies(ModuleDescriptorImpl module, List<ModuleDescriptorImpl> modules) {
168            module.setDependencies(KotlinPackage.plus(modules, KotlinBuiltIns.getInstance().getBuiltInsModule()));
169        }
170    
171        @NotNull
172        public static Collection<JetFile> withJsLibAdded(@NotNull Collection<JetFile> files, @NotNull Config config) {
173            Collection<JetFile> allFiles = Lists.newArrayList();
174            allFiles.addAll(files);
175            allFiles.addAll(config.getSourceFilesFromLibraries());
176            return allFiles;
177        }
178    }