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