KT-3008 Add module kind. Include module kind and module dependencies in metadata

This commit is contained in:
Alexey Andreev
2016-04-08 19:05:03 +03:00
parent 8d055f6952
commit 2909533522
17 changed files with 979 additions and 74 deletions
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.psi.KtFile;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
import java.util.ArrayList;
import java.util.List;
import static org.jetbrains.kotlin.diagnostics.DiagnosticUtils.hasError;
@@ -86,6 +87,8 @@ public final class K2JSTranslator {
expandIsCalls(program, context);
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
return new TranslationResult.Success(config, files, program, diagnostics, moduleDescriptor);
List<String> importedModules = new ArrayList<String>(context.getImportedModules().keySet());
return new TranslationResult.Success(config, files, program, diagnostics, importedModules, moduleDescriptor);
}
}
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilder
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics
import org.jetbrains.kotlin.serialization.js.JsModuleDescriptor
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
import java.io.File
@@ -44,6 +45,7 @@ abstract class TranslationResult protected constructor(val diagnostics: Diagnost
private val files: List<KtFile>,
val program: JsProgram,
diagnostics: Diagnostics,
private val importedModules: List<String>,
private val moduleDescriptor: ModuleDescriptor
) : TranslationResult(diagnostics) {
@Suppress("unused") // Used in kotlin-web-demo in WebDemoTranslatorFacade
@@ -73,7 +75,13 @@ abstract class TranslationResult protected constructor(val diagnostics: Diagnost
if (config.configuration.getBoolean(JSConfigurationKeys.META_INFO)) {
val metaFileName = KotlinJavascriptMetadataUtils.replaceSuffix(outputFile.name)
val metaFileContent = KotlinJavascriptSerializationUtil.metadataAsString(config.moduleId, moduleDescriptor)
val moduleDescription = JsModuleDescriptor(
name = config.moduleId,
data = moduleDescriptor,
kind = config.moduleKind,
imported = importedModules
);
val metaFileContent = KotlinJavascriptSerializationUtil.metadataAsString(moduleDescription)
val sourceFilesForMetaFile = ArrayList(sourceFiles)
val jsMetaFile = SimpleOutputFile(sourceFilesForMetaFile, metaFileName, metaFileContent)
outputFiles.add(jsMetaFile)
@@ -24,7 +24,7 @@ import com.google.dart.compiler.backend.js.ast.metadata.MetadataProperties;
import com.google.dart.compiler.backend.js.ast.metadata.SideEffectKind;
import com.intellij.openapi.util.Factory;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.hash.LinkedHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.ReflectionTypes;
@@ -42,6 +42,7 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject;
import java.util.List;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -109,6 +110,11 @@ public final class StaticContext {
@NotNull
private final JsConfig config;
@NotNull
private final Map<String, JsName> importedModules = new LinkedHashMap<String, JsName>();
private Map<String, JsName> importedModulesSafe;
//TODO: too many parameters in constructor
private StaticContext(
@NotNull JsProgram program,
@@ -165,6 +171,14 @@ public final class StaticContext {
return rootScope;
}
@NotNull
public Map<String, JsName> getImportedModules() {
if (importedModulesSafe == null) {
importedModulesSafe = Collections.unmodifiableMap(importedModules);
}
return importedModulesSafe;
}
@NotNull
public JsScope getScopeForDescriptor(@NotNull DeclarationDescriptor descriptor) {
JsScope scope = scopes.get(descriptor.getOriginal());
@@ -540,6 +554,13 @@ public final class StaticContext {
return null;
}
JsName moduleId = importedModules.get(moduleName);
if (moduleId == null) {
moduleId = rootScope.declareFreshName(suggestedModuleName(moduleName));
importedModules.put(moduleName, moduleId);
}
// TODO: use just generated moduleId to refer to module. This requires to rewrite how JS module is written
return JsAstUtils.replaceRootReference(
result, namer.getModuleReference(program.getStringLiteral(moduleName)));
}
@@ -635,6 +656,40 @@ public final class StaticContext {
}
}
private static String suggestedModuleName(String id) {
if (id.isEmpty()) {
return "_";
}
StringBuilder sb = new StringBuilder(id.length());
char c = id.charAt(0);
if (Character.isJavaIdentifierStart(c)) {
sb.append(c);
}
else {
sb.append('_');
if (Character.isJavaIdentifierPart(c)) {
sb.append(c);
}
}
sb.append(Character.isJavaIdentifierStart(c) ? c : '_');
for (int i = 1; i < id.length(); ++i) {
c = id.charAt(i);
sb.append(Character.isJavaIdentifierPart(c) ? c : '_');
}
return sb.toString();
}
@Nullable
private static ClassDescriptor getEnclosing(@Nullable DeclarationDescriptor descriptor) {
while (descriptor != null && !(descriptor instanceof ClassDescriptor)) {
descriptor = descriptor.getContainingDeclaration();
}
return (ClassDescriptor) descriptor;
}
private static JsExpression applySideEffects(JsExpression expression, DeclarationDescriptor descriptor) {
if (expression instanceof HasMetadata) {
if (descriptor instanceof FunctionDescriptor ||
@@ -91,6 +91,11 @@ public class TranslationContext {
}
}
@NotNull
public Map<String, JsName> getImportedModules() {
return staticContext.getImportedModules();
}
@Nullable
public UsageTracker usageTracker() {
return usageTracker;