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 org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.kotlin.config.CommonConfigurationKeys;
026 import org.jetbrains.kotlin.config.CompilerConfiguration;
027 import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl;
028 import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
029 import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
030 import org.jetbrains.kotlin.js.resolve.JsPlatform;
031 import org.jetbrains.kotlin.name.Name;
032 import org.jetbrains.kotlin.psi.KtFile;
033 import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration;
034 import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor;
035 import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil;
036 import org.jetbrains.kotlin.serialization.js.ModuleKind;
037 import org.jetbrains.kotlin.storage.LockBasedStorageManager;
038 import org.jetbrains.kotlin.utils.JsMetadataVersion;
039 import org.jetbrains.kotlin.utils.KotlinJavascriptMetadata;
040
041 import java.util.ArrayList;
042 import java.util.Collection;
043 import java.util.Collections;
044 import java.util.List;
045
046 /**
047 * Base class representing a configuration of translator.
048 */
049 public abstract class JsConfig {
050 private final Project project;
051 private final CompilerConfiguration configuration;
052 private final LockBasedStorageManager storageManager = new LockBasedStorageManager();
053 private final List<KtFile> sourceFilesFromLibraries = new SmartList<KtFile>();
054
055 @NotNull
056 protected final List<KotlinJavascriptMetadata> metadata = new SmartList<KotlinJavascriptMetadata>();
057
058 @Nullable
059 private List<JsModuleDescriptor<ModuleDescriptorImpl>> moduleDescriptors = null;
060
061 private boolean initialized = false;
062
063 protected JsConfig(@NotNull Project project, @NotNull CompilerConfiguration configuration) {
064 this.project = project;
065 this.configuration = configuration;
066 }
067
068 @NotNull
069 public CompilerConfiguration getConfiguration() {
070 return configuration;
071 }
072
073 @NotNull
074 public Project getProject() {
075 return project;
076 }
077
078 @NotNull
079 public String getModuleId() {
080 return configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME);
081 }
082
083 @NotNull
084 public ModuleKind getModuleKind() {
085 return configuration.get(JSConfigurationKeys.MODULE_KIND, ModuleKind.PLAIN);
086 }
087
088 public static abstract class Reporter {
089 public void error(@NotNull String message) { /*Do nothing*/ }
090 public void warning(@NotNull String message) { /*Do nothing*/ }
091 }
092
093 public abstract boolean checkLibFilesAndReportErrors(@NotNull Reporter report);
094
095 protected abstract void init(@NotNull List<KtFile> sourceFilesInLibraries, @NotNull List<KotlinJavascriptMetadata> metadata);
096
097 @NotNull
098 public List<JsModuleDescriptor<ModuleDescriptorImpl>> getModuleDescriptors() {
099 init();
100 if (moduleDescriptors != null) return moduleDescriptors;
101
102 moduleDescriptors = new SmartList<JsModuleDescriptor<ModuleDescriptorImpl>>();
103 List<ModuleDescriptorImpl> kotlinModuleDescriptors = new ArrayList<ModuleDescriptorImpl>();
104 for (KotlinJavascriptMetadata metadataEntry : metadata) {
105 JsModuleDescriptor<ModuleDescriptorImpl> descriptor = createModuleDescriptor(metadataEntry);
106 moduleDescriptors.add(descriptor);
107 kotlinModuleDescriptors.add(descriptor.getData());
108 }
109
110 for (JsModuleDescriptor<ModuleDescriptorImpl> module : moduleDescriptors) {
111 // TODO: remove downcast
112 setDependencies(module.getData(), kotlinModuleDescriptors);
113 }
114
115 moduleDescriptors = Collections.unmodifiableList(moduleDescriptors);
116
117 return moduleDescriptors;
118 }
119
120 @NotNull
121 private List<KtFile> getSourceFilesFromLibraries() {
122 init();
123 return sourceFilesFromLibraries;
124 }
125
126 private void init() {
127 if (initialized) return;
128
129 init(sourceFilesFromLibraries, metadata);
130 initialized = true;
131 }
132
133 private JsModuleDescriptor<ModuleDescriptorImpl> createModuleDescriptor(KotlinJavascriptMetadata metadata) {
134 assert metadata.getVersion().isCompatible() :
135 "Expected JS metadata version " + JsMetadataVersion.INSTANCE + ", but actual metadata version is " + metadata.getVersion();
136
137 ModuleDescriptorImpl moduleDescriptor = new ModuleDescriptorImpl(
138 Name.special("<" + metadata.getModuleName() + ">"), storageManager, JsPlatform.INSTANCE.getBuiltIns()
139 );
140
141 JsModuleDescriptor<PackageFragmentProvider> rawDescriptor = KotlinJavascriptSerializationUtil.readModule(
142 metadata.getBody(), storageManager, moduleDescriptor, new CompilerDeserializationConfiguration(
143 configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, LanguageVersionSettingsImpl.DEFAULT)
144 )
145 );
146
147 PackageFragmentProvider provider = rawDescriptor.getData();
148 moduleDescriptor.initialize(provider != null ? provider : PackageFragmentProvider.Empty.INSTANCE);
149
150 return rawDescriptor.copy(moduleDescriptor);
151 }
152
153 private static void setDependencies(ModuleDescriptorImpl module, List<ModuleDescriptorImpl> modules) {
154 module.setDependencies(CollectionsKt.plus(modules, JsPlatform.INSTANCE.getBuiltIns().getBuiltInsModule()));
155 }
156
157 @NotNull
158 public static Collection<KtFile> withJsLibAdded(@NotNull Collection<KtFile> files, @NotNull JsConfig config) {
159 Collection<KtFile> allFiles = Lists.newArrayList();
160 allFiles.addAll(files);
161 allFiles.addAll(config.getSourceFilesFromLibraries());
162 return allFiles;
163 }
164 }