JS: add tests for recompilation of only some files in a project
This commit is contained in:
@@ -17,15 +17,14 @@
|
|||||||
package org.jetbrains.kotlin.idea
|
package org.jetbrains.kotlin.idea
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
|
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
|
||||||
class MainFunctionDetector {
|
class MainFunctionDetector {
|
||||||
@@ -68,8 +67,22 @@ class MainFunctionDetector {
|
|||||||
return isMain(getFunctionDescriptor(function))
|
return isMain(getFunctionDescriptor(function))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getMainFunction(files: Collection<KtFile>): KtNamedFunction? =
|
fun getMainFunction(module: ModuleDescriptor): FunctionDescriptor? = getMainFunction(module, module.getPackage(FqName.ROOT))
|
||||||
files.asSequence().map { findMainFunction(it.declarations) }.firstOrNull { it != null }
|
|
||||||
|
private fun getMainFunction(module: ModuleDescriptor, packageView: PackageViewDescriptor): FunctionDescriptor? {
|
||||||
|
for (packageFragment in packageView.fragments) {
|
||||||
|
DescriptorUtils.getAllDescriptors(packageFragment.getMemberScope())
|
||||||
|
.filterIsInstance<FunctionDescriptor>()
|
||||||
|
.firstOrNull { isMain(it) }
|
||||||
|
?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
|
for (subpackageName in module.getSubPackagesOf(packageView.fqName, MemberScope.ALL_NAME_FILTER)) {
|
||||||
|
getMainFunction(module, module.getPackage(subpackageName))?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
private fun findMainFunction(declarations: List<KtDeclaration>) =
|
private fun findMainFunction(declarations: List<KtDeclaration>) =
|
||||||
declarations.filterIsInstance<KtNamedFunction>().find { isMain(it) }
|
declarations.filterIsInstance<KtNamedFunction>().find { isMain(it) }
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import org.jetbrains.kotlin.container.get
|
|||||||
import org.jetbrains.kotlin.container.useImpl
|
import org.jetbrains.kotlin.container.useImpl
|
||||||
import org.jetbrains.kotlin.container.useInstance
|
import org.jetbrains.kotlin.container.useInstance
|
||||||
import org.jetbrains.kotlin.context.ModuleContext
|
import org.jetbrains.kotlin.context.ModuleContext
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.frontend.di.configureModule
|
import org.jetbrains.kotlin.frontend.di.configureModule
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
@@ -30,12 +32,15 @@ import org.jetbrains.kotlin.resolve.*
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer
|
||||||
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
|
||||||
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.DeserializationConfiguration
|
||||||
|
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil
|
||||||
|
|
||||||
fun createTopDownAnalyzerForJs(
|
fun createTopDownAnalyzerForJs(
|
||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
bindingTrace: BindingTrace,
|
bindingTrace: BindingTrace,
|
||||||
declarationProviderFactory: DeclarationProviderFactory,
|
declarationProviderFactory: DeclarationProviderFactory,
|
||||||
languageVersionSettings: LanguageVersionSettings
|
languageVersionSettings: LanguageVersionSettings,
|
||||||
|
fallbackMetadata: List<ByteArray> = emptyList()
|
||||||
): LazyTopDownAnalyzer {
|
): LazyTopDownAnalyzer {
|
||||||
val storageComponentContainer = createContainer("TopDownAnalyzerForJs", JsPlatform) {
|
val storageComponentContainer = createContainer("TopDownAnalyzerForJs", JsPlatform) {
|
||||||
configureModule(moduleContext, JsPlatform, TargetPlatformVersion.NoVersion, bindingTrace)
|
configureModule(moduleContext, JsPlatform, TargetPlatformVersion.NoVersion, bindingTrace)
|
||||||
@@ -50,7 +55,13 @@ fun createTopDownAnalyzerForJs(
|
|||||||
useImpl<ResolveSession>()
|
useImpl<ResolveSession>()
|
||||||
useImpl<LazyTopDownAnalyzer>()
|
useImpl<LazyTopDownAnalyzer>()
|
||||||
}.apply {
|
}.apply {
|
||||||
get<ModuleDescriptorImpl>().initialize(get<KotlinCodeAnalyzer>().packageFragmentProvider)
|
val packagePartProviders = mutableListOf<PackageFragmentProvider>(get<KotlinCodeAnalyzer>().packageFragmentProvider)
|
||||||
|
val moduleDescriptor = get<ModuleDescriptorImpl>()
|
||||||
|
if (fallbackMetadata.isNotEmpty()) {
|
||||||
|
packagePartProviders += KotlinJavascriptSerializationUtil.readScope(
|
||||||
|
fallbackMetadata, moduleContext.storageManager, moduleDescriptor, DeserializationConfiguration.Default)
|
||||||
|
}
|
||||||
|
moduleDescriptor.initialize(CompositePackageFragmentProvider(packagePartProviders))
|
||||||
}
|
}
|
||||||
return storageComponentContainer.get<LazyTopDownAnalyzer>()
|
return storageComponentContainer.get<LazyTopDownAnalyzer>()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.context.ModuleContext
|
|||||||
import org.jetbrains.kotlin.context.ProjectContext
|
import org.jetbrains.kotlin.context.ProjectContext
|
||||||
import org.jetbrains.kotlin.frontend.js.di.createTopDownAnalyzerForJs
|
import org.jetbrains.kotlin.frontend.js.di.createTopDownAnalyzerForJs
|
||||||
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
|
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult
|
||||||
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig
|
import org.jetbrains.kotlin.js.config.JsConfig
|
||||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||||
import org.jetbrains.kotlin.js.resolve.MODULE_KIND
|
import org.jetbrains.kotlin.js.resolve.MODULE_KIND
|
||||||
@@ -56,7 +57,8 @@ object TopDownAnalyzerFacadeForJS {
|
|||||||
val analyzerForJs = createTopDownAnalyzerForJs(
|
val analyzerForJs = createTopDownAnalyzerForJs(
|
||||||
moduleContext, trace,
|
moduleContext, trace,
|
||||||
FileBasedDeclarationProviderFactory(moduleContext.storageManager, files),
|
FileBasedDeclarationProviderFactory(moduleContext.storageManager, files),
|
||||||
config.configuration.languageVersionSettings
|
config.configuration.languageVersionSettings,
|
||||||
|
config.configuration[JSConfigurationKeys.FALLBACK_METADATA].orEmpty()
|
||||||
)
|
)
|
||||||
analyzerForJs.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
analyzerForJs.analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, files)
|
||||||
return JsAnalysisResult.success(trace, moduleContext.module)
|
return JsAnalysisResult.success(trace, moduleContext.module)
|
||||||
|
|||||||
@@ -39,4 +39,9 @@ public class JSConfigurationKeys {
|
|||||||
|
|
||||||
public static final CompilerConfigurationKey<Boolean> TYPED_ARRAYS_ENABLED =
|
public static final CompilerConfigurationKey<Boolean> TYPED_ARRAYS_ENABLED =
|
||||||
CompilerConfigurationKey.create("TypedArrays enabled");
|
CompilerConfigurationKey.create("TypedArrays enabled");
|
||||||
|
|
||||||
|
public static final CompilerConfigurationKey<List<byte[]>> FALLBACK_METADATA =
|
||||||
|
CompilerConfigurationKey.create("fallback metadata");
|
||||||
|
|
||||||
|
public static final CompilerConfigurationKey<Boolean> SERIALIZE_FRAGMENTS = CompilerConfigurationKey.create("serialize fragments");
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-11
@@ -51,7 +51,17 @@ object KotlinJavascriptSerializationUtil {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun serializeMetadata(
|
fun readScope(
|
||||||
|
metadata: Collection<ByteArray>,
|
||||||
|
storageManager: StorageManager,
|
||||||
|
module: ModuleDescriptor,
|
||||||
|
configuration: DeserializationConfiguration
|
||||||
|
): PackageFragmentProvider {
|
||||||
|
val scopeProto = metadata.map { JsProtoBuf.Library.Part.parseFrom(it) }
|
||||||
|
return createKotlinJavascriptPackageFragmentProvider(storageManager, module, scopeProto, configuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun serializeMetadata(
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
moduleKind: ModuleKind,
|
moduleKind: ModuleKind,
|
||||||
@@ -84,10 +94,18 @@ object KotlinJavascriptSerializationUtil {
|
|||||||
fun metadataAsString(bindingContext: BindingContext, jsDescriptor: JsModuleDescriptor<ModuleDescriptor>): String =
|
fun metadataAsString(bindingContext: BindingContext, jsDescriptor: JsModuleDescriptor<ModuleDescriptor>): String =
|
||||||
KotlinJavascriptMetadataUtils.formatMetadataAsString(jsDescriptor.name, jsDescriptor.serializeToBinaryMetadata(bindingContext))
|
KotlinJavascriptMetadataUtils.formatMetadataAsString(jsDescriptor.name, jsDescriptor.serializeToBinaryMetadata(bindingContext))
|
||||||
|
|
||||||
private fun serializePackageFragment(bindingContext: BindingContext, module: ModuleDescriptor, fqName: FqName): ProtoBuf.PackageFragment {
|
fun serializePackage(bindingContext: BindingContext, module: ModuleDescriptor, fqName: FqName): JsProtoBuf.Library.Part {
|
||||||
val builder = ProtoBuf.PackageFragment.newBuilder()
|
|
||||||
|
|
||||||
val packageView = module.getPackage(fqName)
|
val packageView = module.getPackage(fqName)
|
||||||
|
return serializeScope(bindingContext, module, packageView.memberScope.getContributedDescriptors(), fqName)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun serializeScope(
|
||||||
|
bindingContext: BindingContext,
|
||||||
|
module: ModuleDescriptor,
|
||||||
|
scope: Collection<DeclarationDescriptor>,
|
||||||
|
fqName: FqName
|
||||||
|
): JsProtoBuf.Library.Part {
|
||||||
|
val builder = JsProtoBuf.Library.Part.newBuilder()
|
||||||
|
|
||||||
// TODO: ModuleDescriptor should be able to return the package only with the contents of that module, without dependencies
|
// TODO: ModuleDescriptor should be able to return the package only with the contents of that module, without dependencies
|
||||||
val skip: (DeclarationDescriptor) -> Boolean = { DescriptorUtils.getContainingModule(it) != module || (it is MemberDescriptor && it.isHeader) }
|
val skip: (DeclarationDescriptor) -> Boolean = { DescriptorUtils.getContainingModule(it) != module || (it is MemberDescriptor && it.isHeader) }
|
||||||
@@ -96,9 +114,7 @@ object KotlinJavascriptSerializationUtil {
|
|||||||
val serializerExtension = KotlinJavascriptSerializerExtension(fileRegistry)
|
val serializerExtension = KotlinJavascriptSerializerExtension(fileRegistry)
|
||||||
val serializer = DescriptorSerializer.createTopLevel(serializerExtension)
|
val serializer = DescriptorSerializer.createTopLevel(serializerExtension)
|
||||||
|
|
||||||
val classDescriptors = DescriptorSerializer.sort(
|
val classDescriptors = DescriptorSerializer.sort(scope).filterIsInstance<ClassDescriptor>()
|
||||||
packageView.memberScope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)
|
|
||||||
).filterIsInstance<ClassDescriptor>()
|
|
||||||
|
|
||||||
fun serializeClasses(descriptors: Collection<DeclarationDescriptor>) {
|
fun serializeClasses(descriptors: Collection<DeclarationDescriptor>) {
|
||||||
fun serializeClass(classDescriptor: ClassDescriptor) {
|
fun serializeClass(classDescriptor: ClassDescriptor) {
|
||||||
@@ -119,10 +135,7 @@ object KotlinJavascriptSerializationUtil {
|
|||||||
|
|
||||||
val stringTable = serializerExtension.stringTable
|
val stringTable = serializerExtension.stringTable
|
||||||
|
|
||||||
val fragments = packageView.fragments
|
val members = scope.filterNot(skip)
|
||||||
val members = fragments
|
|
||||||
.flatMap { fragment -> DescriptorUtils.getAllDescriptors(fragment.getMemberScope()) }
|
|
||||||
.filterNot(skip)
|
|
||||||
builder.`package` = serializer.packagePartProto(fqName, members).build()
|
builder.`package` = serializer.packagePartProto(fqName, members).build()
|
||||||
|
|
||||||
builder.setExtension(
|
builder.setExtension(
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.text.StringUtil
|
|||||||
import com.intellij.openapi.vfs.StandardFileSystems
|
import com.intellij.openapi.vfs.StandardFileSystems
|
||||||
import com.intellij.openapi.vfs.VirtualFileManager
|
import com.intellij.openapi.vfs.VirtualFileManager
|
||||||
import com.intellij.psi.PsiManager
|
import com.intellij.psi.PsiManager
|
||||||
|
import junit.framework.TestCase
|
||||||
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
|
||||||
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.PrintingMessageCollector
|
||||||
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.js.config.JsConfig
|
|||||||
import org.jetbrains.kotlin.js.facade.K2JSTranslator
|
import org.jetbrains.kotlin.js.facade.K2JSTranslator
|
||||||
import org.jetbrains.kotlin.js.facade.MainCallParameters
|
import org.jetbrains.kotlin.js.facade.MainCallParameters
|
||||||
import org.jetbrains.kotlin.js.facade.TranslationResult
|
import org.jetbrains.kotlin.js.facade.TranslationResult
|
||||||
|
import org.jetbrains.kotlin.js.facade.TranslationUnit
|
||||||
import org.jetbrains.kotlin.js.test.rhino.RhinoFunctionResultChecker
|
import org.jetbrains.kotlin.js.test.rhino.RhinoFunctionResultChecker
|
||||||
import org.jetbrains.kotlin.js.test.rhino.RhinoUtils
|
import org.jetbrains.kotlin.js.test.rhino.RhinoUtils
|
||||||
import org.jetbrains.kotlin.js.test.utils.DirectiveTestUtils
|
import org.jetbrains.kotlin.js.test.utils.DirectiveTestUtils
|
||||||
@@ -227,7 +229,8 @@ abstract class BasicBoxTest(
|
|||||||
outputPostfixFile: File?,
|
outputPostfixFile: File?,
|
||||||
mainCallParameters: MainCallParameters
|
mainCallParameters: MainCallParameters
|
||||||
) {
|
) {
|
||||||
val testFiles = module.files.map { it.fileName }.filter { it.endsWith(".kt") }
|
val kotlinFiles = module.files.filter { it.fileName.endsWith(".kt") }
|
||||||
|
val testFiles = kotlinFiles.map { it.fileName }
|
||||||
val globalCommonFiles = JsTestUtils.getFilesInDirectoryByExtension(
|
val globalCommonFiles = JsTestUtils.getFilesInDirectoryByExtension(
|
||||||
TEST_DATA_DIR_PATH + COMMON_FILES_DIR, KotlinFileType.EXTENSION)
|
TEST_DATA_DIR_PATH + COMMON_FILES_DIR, KotlinFileType.EXTENSION)
|
||||||
val localCommonFile = directory + "/" + COMMON_FILES_NAME + "." + KotlinFileType.EXTENSION
|
val localCommonFile = directory + "/" + COMMON_FILES_NAME + "." + KotlinFileType.EXTENSION
|
||||||
@@ -235,24 +238,47 @@ abstract class BasicBoxTest(
|
|||||||
val additionalCommonFiles = additionalCommonFileDirectories.flatMap { baseDir ->
|
val additionalCommonFiles = additionalCommonFileDirectories.flatMap { baseDir ->
|
||||||
JsTestUtils.getFilesInDirectoryByExtension(baseDir + "/", KotlinFileType.EXTENSION)
|
JsTestUtils.getFilesInDirectoryByExtension(baseDir + "/", KotlinFileType.EXTENSION)
|
||||||
}
|
}
|
||||||
val psiFiles = createPsiFiles(testFiles + globalCommonFiles + localCommonFiles + additionalCommonFiles)
|
val additionalFiles = globalCommonFiles + localCommonFiles + additionalCommonFiles
|
||||||
|
val psiFiles = createPsiFiles(testFiles + additionalFiles)
|
||||||
|
|
||||||
val config = createConfig(module, dependencies, multiModule)
|
val config = createConfig(module, dependencies, multiModule, additionalMetadata = null)
|
||||||
val outputFile = File(outputFileName)
|
val outputFile = File(outputFileName)
|
||||||
|
|
||||||
translateFiles(psiFiles, outputFile, config, outputPrefixFile, outputPostfixFile, mainCallParameters)
|
translateFiles(psiFiles.map(TranslationUnit::SourceFile), outputFile, config, outputPrefixFile, outputPostfixFile, mainCallParameters)
|
||||||
}
|
|
||||||
|
|
||||||
protected fun translateFiles(
|
if (module.hasFilesToRecompile) {
|
||||||
psiFiles: List<KtFile>,
|
val incrementalDir = File(outputFile.parentFile, "incremental/" + outputFile.nameWithoutExtension)
|
||||||
outputFile: File,
|
val serializedMetadata = mutableListOf<File>()
|
||||||
config: JsConfig,
|
val translationUnits = kotlinFiles.withIndex().map { (index, file) ->
|
||||||
|
if (file.recompile) {
|
||||||
|
TranslationUnit.SourceFile(createPsiFile(file.fileName))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
serializedMetadata += File(incrementalDir, "$index.$METADATA_EXTENSION")
|
||||||
|
val astFile = File(incrementalDir, "$index.$AST_EXTENSION")
|
||||||
|
TranslationUnit.BinaryAst(FileUtil.loadFileBytes(astFile))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val allTranslationUnits = translationUnits + additionalFiles.withIndex().map { (index, _) ->
|
||||||
|
val astFile = File(incrementalDir, "${index + translationUnits.size}.$AST_EXTENSION")
|
||||||
|
TranslationUnit.BinaryAst(FileUtil.loadFileBytes(astFile))
|
||||||
|
}
|
||||||
|
|
||||||
|
val recompiledConfig = createConfig(module, dependencies, multiModule, serializedMetadata)
|
||||||
|
val recompiledOutputFile = File(outputFile.parentFile, outputFile.nameWithoutExtension + "-recompiled.js")
|
||||||
|
|
||||||
|
translateFiles(allTranslationUnits, recompiledOutputFile, recompiledConfig)
|
||||||
|
|
||||||
|
val originalOutput = FileUtil.loadFile(outputFile)
|
||||||
|
val recompiledOutput = FileUtil.loadFile(recompiledOutputFile)
|
||||||
|
TestCase.assertEquals("Output file changed after recompilation", originalOutput, recompiledOutput)
|
||||||
|
}
|
||||||
|
}protected fun translateFiles(units: List<TranslationUnit>, outputFile: File, config: JsConfig,
|
||||||
outputPrefixFile: File?,
|
outputPrefixFile: File?,
|
||||||
outputPostfixFile: File?,
|
outputPostfixFile: File?,
|
||||||
mainCallParameters: MainCallParameters
|
mainCallParameters: MainCallParameters) {
|
||||||
) {
|
|
||||||
val translator = K2JSTranslator(config)
|
val translator = K2JSTranslator(config)
|
||||||
val translationResult = translator.translate(psiFiles, mainCallParameters)
|
val translationResult = translator.translateUnits(units, mainCallParameters)
|
||||||
|
|
||||||
if (translationResult !is TranslationResult.Success) {
|
if (translationResult !is TranslationResult.Success) {
|
||||||
val outputStream = ByteArrayOutputStream()
|
val outputStream = ByteArrayOutputStream()
|
||||||
@@ -281,7 +307,24 @@ abstract class BasicBoxTest(
|
|||||||
FileUtil.writeToFile(outputFile, wrappedContent)
|
FileUtil.writeToFile(outputFile, wrappedContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
processJsProgram(translationResult.program, psiFiles)
|
val incrementalDir = File(outputDir, "incremental/${outputFile.nameWithoutExtension}")
|
||||||
|
|
||||||
|
for ((index, unit) in units.withIndex()) {
|
||||||
|
if (unit !is TranslationUnit.SourceFile) continue
|
||||||
|
val fileTranslationResult = translationResult.fileTranslationResults[unit.file]!!
|
||||||
|
val basePath = "$index."
|
||||||
|
val binaryAst = fileTranslationResult.binaryAst
|
||||||
|
val binaryMetadata = fileTranslationResult.metadata
|
||||||
|
|
||||||
|
if (binaryAst != null) {
|
||||||
|
FileUtil.writeToFile(File(incrementalDir, basePath + AST_EXTENSION), binaryAst)
|
||||||
|
}
|
||||||
|
if (binaryMetadata != null) {
|
||||||
|
FileUtil.writeToFile(File(incrementalDir, basePath + METADATA_EXTENSION), binaryMetadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processJsProgram(translationResult.program, units.filterIsInstance<TranslationUnit.SourceFile>().map { it.file })
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun processJsProgram(program: JsProgram, psiFiles: List<KtFile>) {
|
protected fun processJsProgram(program: JsProgram, psiFiles: List<KtFile>) {
|
||||||
@@ -291,14 +334,19 @@ abstract class BasicBoxTest(
|
|||||||
program.verifyAst()
|
program.verifyAst()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createPsiFiles(fileNames: List<String>): List<KtFile> {
|
private fun createPsiFile(fileName: String): KtFile {
|
||||||
val psiManager = PsiManager.getInstance(project)
|
val psiManager = PsiManager.getInstance(project)
|
||||||
val fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
val fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
|
||||||
|
|
||||||
return fileNames.map { fileName -> psiManager.findFile(fileSystem.findFileByPath(fileName)!!) as KtFile }
|
return psiManager.findFile(fileSystem.findFileByPath(fileName)!!) as KtFile
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createConfig(module: TestModule, dependencies: List<String>, multiModule: Boolean): JsConfig {
|
private fun createPsiFiles(fileNames: List<String>): List<KtFile> = fileNames.map(this::createPsiFile)
|
||||||
|
|
||||||
|
private fun createConfig(
|
||||||
|
module: TestModule, dependencies: List<String>, multiModule: Boolean,
|
||||||
|
additionalMetadata: List<File>?
|
||||||
|
): JsConfig {
|
||||||
val configuration = environment.configuration.copy()
|
val configuration = environment.configuration.copy()
|
||||||
|
|
||||||
configuration.put(CommonConfigurationKeys.DISABLE_INLINE, module.inliningDisabled)
|
configuration.put(CommonConfigurationKeys.DISABLE_INLINE, module.inliningDisabled)
|
||||||
@@ -314,7 +362,13 @@ abstract class BasicBoxTest(
|
|||||||
configuration.put(JSConfigurationKeys.TARGET, EcmaVersion.v5)
|
configuration.put(JSConfigurationKeys.TARGET, EcmaVersion.v5)
|
||||||
|
|
||||||
configuration.put(JSConfigurationKeys.SOURCE_MAP, generateSourceMap)
|
configuration.put(JSConfigurationKeys.SOURCE_MAP, generateSourceMap)
|
||||||
|
val hasFilesToRecompile = module.hasFilesToRecompile
|
||||||
configuration.put(JSConfigurationKeys.META_INFO, multiModule)
|
configuration.put(JSConfigurationKeys.META_INFO, multiModule)
|
||||||
|
configuration.put(JSConfigurationKeys.SERIALIZE_FRAGMENTS, hasFilesToRecompile)
|
||||||
|
|
||||||
|
if (additionalMetadata != null) {
|
||||||
|
configuration.put(JSConfigurationKeys.FALLBACK_METADATA, additionalMetadata.map { FileUtil.loadFileBytes(it) })
|
||||||
|
}
|
||||||
|
|
||||||
if (typedArraysEnabled) {
|
if (typedArraysEnabled) {
|
||||||
configuration.put(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, true)
|
configuration.put(JSConfigurationKeys.TYPED_ARRAYS_ENABLED, true)
|
||||||
@@ -359,7 +413,9 @@ abstract class BasicBoxTest(
|
|||||||
currentModule.languageVersion = LanguageVersion.fromVersionString(version)
|
currentModule.languageVersion = LanguageVersion.fromVersionString(version)
|
||||||
}
|
}
|
||||||
|
|
||||||
return TestFile(temporaryFile.absolutePath, currentModule)
|
return TestFile(temporaryFile.absolutePath, currentModule).apply {
|
||||||
|
recompile = RECOMPILE_PATTERN.matcher(text).find()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createModule(name: String, dependencies: List<String>): TestModule? {
|
override fun createModule(name: String, dependencies: List<String>): TestModule? {
|
||||||
@@ -375,6 +431,8 @@ abstract class BasicBoxTest(
|
|||||||
init {
|
init {
|
||||||
module.files += this
|
module.files += this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var recompile = false
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestModule(
|
private class TestModule(
|
||||||
@@ -386,6 +444,8 @@ abstract class BasicBoxTest(
|
|||||||
var inliningDisabled = false
|
var inliningDisabled = false
|
||||||
val files = mutableListOf<TestFile>()
|
val files = mutableListOf<TestFile>()
|
||||||
var languageVersion: LanguageVersion? = null
|
var languageVersion: LanguageVersion? = null
|
||||||
|
|
||||||
|
val hasFilesToRecompile get() = files.any { it.recompile }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createEnvironment(): KotlinCoreEnvironment {
|
override fun createEnvironment(): KotlinCoreEnvironment {
|
||||||
@@ -404,6 +464,9 @@ abstract class BasicBoxTest(
|
|||||||
private val NO_MODULE_SYSTEM_PATTERN = Pattern.compile("^// *NO_JS_MODULE_SYSTEM", Pattern.MULTILINE)
|
private val NO_MODULE_SYSTEM_PATTERN = Pattern.compile("^// *NO_JS_MODULE_SYSTEM", Pattern.MULTILINE)
|
||||||
private val NO_INLINE_PATTERN = Pattern.compile("^// *NO_INLINE *$", Pattern.MULTILINE)
|
private val NO_INLINE_PATTERN = Pattern.compile("^// *NO_INLINE *$", Pattern.MULTILINE)
|
||||||
private val SKIP_NODE_JS = Pattern.compile("^// *SKIP_NODE_JS *$", Pattern.MULTILINE)
|
private val SKIP_NODE_JS = Pattern.compile("^// *SKIP_NODE_JS *$", Pattern.MULTILINE)
|
||||||
|
private val RECOMPILE_PATTERN = Pattern.compile("^// *RECOMPILE *$", Pattern.MULTILINE)
|
||||||
|
private val AST_EXTENSION = "jsast"
|
||||||
|
private val METADATA_EXTENSION = "jsmeta"
|
||||||
|
|
||||||
private val TEST_MODULE = "JS_TESTS"
|
private val TEST_MODULE = "JS_TESTS"
|
||||||
private val DEFAULT_MODULE = "main"
|
private val DEFAULT_MODULE = "main"
|
||||||
|
|||||||
@@ -3435,6 +3435,21 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("js/js.translator/testData/box/incremental")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Incremental extends AbstractBoxJsTest {
|
||||||
|
public void testAllFilesPresentInIncremental() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/incremental"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simple.kt")
|
||||||
|
public void testSimple() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/incremental/simple.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("js/js.translator/testData/box/inheritance")
|
@TestMetadata("js/js.translator/testData/box/inheritance")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -18,12 +18,13 @@ package org.jetbrains.kotlin.js.facade;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||||
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS;
|
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS;
|
||||||
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult;
|
import org.jetbrains.kotlin.js.analyzer.JsAnalysisResult;
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsImportedModule;
|
import org.jetbrains.kotlin.js.backend.ast.JsImportedModule;
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram;
|
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsProgramFragment;
|
import org.jetbrains.kotlin.js.backend.ast.JsProgramFragment;
|
||||||
|
import org.jetbrains.kotlin.js.config.JSConfigurationKeys;
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||||
import org.jetbrains.kotlin.js.coroutine.CoroutineTransformer;
|
import org.jetbrains.kotlin.js.coroutine.CoroutineTransformer;
|
||||||
import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
|
import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
|
||||||
@@ -31,19 +32,22 @@ import org.jetbrains.kotlin.js.inline.JsInliner;
|
|||||||
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedImportsKt;
|
import org.jetbrains.kotlin.js.inline.clean.RemoveUnusedImportsKt;
|
||||||
import org.jetbrains.kotlin.js.inline.clean.ResolveTemporaryNamesKt;
|
import org.jetbrains.kotlin.js.inline.clean.ResolveTemporaryNamesKt;
|
||||||
import org.jetbrains.kotlin.js.translate.general.AstGenerationResult;
|
import org.jetbrains.kotlin.js.translate.general.AstGenerationResult;
|
||||||
|
import org.jetbrains.kotlin.js.translate.general.FileTranslationResult;
|
||||||
import org.jetbrains.kotlin.js.translate.general.Translation;
|
import org.jetbrains.kotlin.js.translate.general.Translation;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.ExpandIsCallsKt;
|
import org.jetbrains.kotlin.js.translate.utils.ExpandIsCallsKt;
|
||||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
|
import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics;
|
||||||
import org.jetbrains.kotlin.serialization.js.ast.JsAstDeserializer;
|
import org.jetbrains.kotlin.serialization.js.JsProtoBuf;
|
||||||
|
import org.jetbrains.kotlin.serialization.js.KotlinJavascriptSerializationUtil;
|
||||||
import org.jetbrains.kotlin.serialization.js.ast.JsAstSerializer;
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstSerializer;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.diagnostics.DiagnosticUtils.hasError;
|
import static org.jetbrains.kotlin.diagnostics.DiagnosticUtils.hasError;
|
||||||
|
|
||||||
@@ -73,6 +77,34 @@ public final class K2JSTranslator {
|
|||||||
@NotNull MainCallParameters mainCallParameters,
|
@NotNull MainCallParameters mainCallParameters,
|
||||||
@Nullable JsAnalysisResult analysisResult
|
@Nullable JsAnalysisResult analysisResult
|
||||||
) throws TranslationException {
|
) throws TranslationException {
|
||||||
|
List<TranslationUnit> units = new ArrayList<TranslationUnit>();
|
||||||
|
for (KtFile file : files) {
|
||||||
|
units.add(new TranslationUnit.SourceFile(file));
|
||||||
|
}
|
||||||
|
return translateUnits(units, mainCallParameters, analysisResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public TranslationResult translateUnits(
|
||||||
|
@NotNull List<TranslationUnit> units,
|
||||||
|
@NotNull MainCallParameters mainCallParameters
|
||||||
|
) throws TranslationException {
|
||||||
|
return translateUnits(units, mainCallParameters, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public TranslationResult translateUnits(
|
||||||
|
@NotNull List<TranslationUnit> units,
|
||||||
|
@NotNull MainCallParameters mainCallParameters,
|
||||||
|
@Nullable JsAnalysisResult analysisResult
|
||||||
|
) throws TranslationException {
|
||||||
|
List<KtFile> files = new ArrayList<KtFile>();
|
||||||
|
for (TranslationUnit unit : units) {
|
||||||
|
if (unit instanceof TranslationUnit.SourceFile) {
|
||||||
|
files.add(((TranslationUnit.SourceFile) unit).getFile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (analysisResult == null) {
|
if (analysisResult == null) {
|
||||||
analysisResult = TopDownAnalyzerFacadeForJS.analyzeFiles(files, config);
|
analysisResult = TopDownAnalyzerFacadeForJS.analyzeFiles(files, config);
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||||
@@ -83,33 +115,39 @@ public final class K2JSTranslator {
|
|||||||
ModuleDescriptor moduleDescriptor = analysisResult.getModuleDescriptor();
|
ModuleDescriptor moduleDescriptor = analysisResult.getModuleDescriptor();
|
||||||
Diagnostics diagnostics = bindingTrace.getBindingContext().getDiagnostics();
|
Diagnostics diagnostics = bindingTrace.getBindingContext().getDiagnostics();
|
||||||
|
|
||||||
AstGenerationResult translationResult = Translation.generateAst(bindingTrace, files, mainCallParameters, moduleDescriptor, config);
|
AstGenerationResult translationResult = Translation.generateAst(bindingTrace, units, mainCallParameters, moduleDescriptor, config);
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||||
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
||||||
|
|
||||||
JsInliner.process(config, analysisResult.getBindingTrace(), translationResult.getInnerModuleName(),
|
List<JsProgramFragment> newFragments = translationResult.getFragments();
|
||||||
translationResult.getFragments(), translationResult.getFragments());
|
List<JsProgramFragment> allFragments = new ArrayList<JsProgramFragment>(newFragments);
|
||||||
|
|
||||||
// TODO: temporary code for testing purposes, remove later
|
JsInliner.process(config, analysisResult.getBindingTrace(), translationResult.getInnerModuleName(), allFragments, newFragments);
|
||||||
|
|
||||||
|
Map<KtFile, FileTranslationResult> fileMap = new HashMap<KtFile, FileTranslationResult>();
|
||||||
JsAstSerializer serializer = new JsAstSerializer();
|
JsAstSerializer serializer = new JsAstSerializer();
|
||||||
JsAstDeserializer deserializer = new JsAstDeserializer(new JsProgram());
|
boolean serializeFragments = config.getConfiguration().get(JSConfigurationKeys.SERIALIZE_FRAGMENTS, false);
|
||||||
JsProgram program = translationResult.getProgram();
|
for (KtFile file : files) {
|
||||||
int bytesTotal = 0;
|
List<DeclarationDescriptor> scope = translationResult.getFileMemberScopes().get(file);
|
||||||
for (JsProgramFragment fragment : translationResult.getFragments()) {
|
byte[] binaryAst = null;
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
byte[] binaryMetadata = null;
|
||||||
serializer.serialize(fragment, output);
|
if (serializeFragments) {
|
||||||
bytesTotal += output.size();
|
JsProgramFragment fragment = translationResult.getFragmentMap().get(file);
|
||||||
|
if (fragment != null) {
|
||||||
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
|
serializer.serialize(fragment, output);
|
||||||
|
binaryAst = output.toByteArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
|
if (scope != null) {
|
||||||
JsProgramFragment deserializedFragment = deserializer.deserialize(input);
|
JsProtoBuf.Library.Part part = KotlinJavascriptSerializationUtil.INSTANCE.serializeScope(
|
||||||
|
bindingTrace.getBindingContext(), moduleDescriptor, scope, file.getPackageFqName());
|
||||||
String expected = fragmentToString(fragment);
|
binaryMetadata = part.toByteArray();
|
||||||
String actual = fragmentToString(deserializedFragment);
|
}
|
||||||
assert expected.equals(actual) : "Deserialization: " + expected + "\n\nvs.\n\n" + actual;
|
fileMap.put(file, new FileTranslationResult(file, binaryMetadata, binaryAst));
|
||||||
}
|
}
|
||||||
|
|
||||||
program.getGlobalBlock().getStatements().add(program.getNumberLiteral(bytesTotal).makeStmt());
|
|
||||||
|
|
||||||
ResolveTemporaryNamesKt.resolveTemporaryNames(translationResult.getProgram());
|
ResolveTemporaryNamesKt.resolveTemporaryNames(translationResult.getProgram());
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||||
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
||||||
@@ -120,7 +158,7 @@ public final class K2JSTranslator {
|
|||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||||
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
if (hasError(diagnostics)) return new TranslationResult.Fail(diagnostics);
|
||||||
|
|
||||||
ExpandIsCallsKt.expandIsCalls(translationResult.getFragments());
|
ExpandIsCallsKt.expandIsCalls(newFragments);
|
||||||
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled();
|
||||||
|
|
||||||
List<String> importedModules = new ArrayList<>();
|
List<String> importedModules = new ArrayList<>();
|
||||||
@@ -128,11 +166,6 @@ public final class K2JSTranslator {
|
|||||||
importedModules.add(module.getExternalName());
|
importedModules.add(module.getExternalName());
|
||||||
}
|
}
|
||||||
return new TranslationResult.Success(config, files, translationResult.getProgram(), diagnostics, importedModules,
|
return new TranslationResult.Success(config, files, translationResult.getProgram(), diagnostics, importedModules,
|
||||||
moduleDescriptor, bindingTrace.getBindingContext());
|
moduleDescriptor, bindingTrace.getBindingContext(), fileMap);
|
||||||
}
|
|
||||||
|
|
||||||
private static String fragmentToString(JsProgramFragment fragment) {
|
|
||||||
return fragment.getDeclarationBlock().toString() + fragment.getInitializerBlock().toString() +
|
|
||||||
fragment.getExportBlock().toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.js.config.JsConfig
|
|||||||
import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor
|
import org.jetbrains.kotlin.js.sourceMap.JsSourceGenerationVisitor
|
||||||
import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
|
import org.jetbrains.kotlin.js.sourceMap.SourceMap3Builder
|
||||||
import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilder
|
import org.jetbrains.kotlin.js.sourceMap.SourceMapBuilder
|
||||||
|
import org.jetbrains.kotlin.js.translate.general.FileTranslationResult
|
||||||
import org.jetbrains.kotlin.js.util.TextOutput
|
import org.jetbrains.kotlin.js.util.TextOutput
|
||||||
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
import org.jetbrains.kotlin.js.util.TextOutputImpl
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
@@ -47,7 +48,8 @@ abstract class TranslationResult protected constructor(val diagnostics: Diagnost
|
|||||||
diagnostics: Diagnostics,
|
diagnostics: Diagnostics,
|
||||||
private val importedModules: List<String>,
|
private val importedModules: List<String>,
|
||||||
private val moduleDescriptor: ModuleDescriptor,
|
private val moduleDescriptor: ModuleDescriptor,
|
||||||
private val bindingContext: BindingContext
|
private val bindingContext: BindingContext,
|
||||||
|
val fileTranslationResults: Map<KtFile, FileTranslationResult>
|
||||||
) : TranslationResult(diagnostics) {
|
) : TranslationResult(diagnostics) {
|
||||||
@Suppress("unused") // Used in kotlin-web-demo in WebDemoTranslatorFacade
|
@Suppress("unused") // Used in kotlin-web-demo in WebDemoTranslatorFacade
|
||||||
fun getCode(): String = getCode(TextOutputImpl(), sourceMapBuilder = null)
|
fun getCode(): String = getCode(TextOutputImpl(), sourceMapBuilder = null)
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.facade
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
|
sealed class TranslationUnit {
|
||||||
|
class SourceFile(val file: KtFile) : TranslationUnit()
|
||||||
|
|
||||||
|
class BinaryAst(val data: ByteArray) : TranslationUnit()
|
||||||
|
}
|
||||||
@@ -16,14 +16,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.js.translate.general
|
package org.jetbrains.kotlin.js.translate.general
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsImportedModule
|
import org.jetbrains.kotlin.js.backend.ast.JsImportedModule
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsName
|
import org.jetbrains.kotlin.js.backend.ast.JsName
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
import org.jetbrains.kotlin.js.backend.ast.JsProgram
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsProgramFragment
|
import org.jetbrains.kotlin.js.backend.ast.JsProgramFragment
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
class AstGenerationResult(
|
class AstGenerationResult(
|
||||||
val program: JsProgram,
|
val program: JsProgram,
|
||||||
val innerModuleName: JsName,
|
val innerModuleName: JsName,
|
||||||
val fragments: List<JsProgramFragment>,
|
val fragments: List<JsProgramFragment>,
|
||||||
|
val fragmentMap: Map<KtFile, JsProgramFragment>,
|
||||||
|
val fileMemberScopes: Map<KtFile, List<DeclarationDescriptor>>,
|
||||||
val importedModuleList: List<JsImportedModule>
|
val importedModuleList: List<JsImportedModule>
|
||||||
)
|
)
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.js.translate.general
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
|
||||||
|
class FileTranslationResult(val file: KtFile, val metadata: ByteArray?, val binaryAst: ByteArray?)
|
||||||
+38
-41
@@ -19,17 +19,10 @@ package org.jetbrains.kotlin.js.translate.general;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality;
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
import org.jetbrains.kotlin.psi.KtClass;
|
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
@@ -66,50 +59,54 @@ public class JetTestFunctionDetector {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static List<FunctionDescriptor> getTestFunctionDescriptors(
|
public static List<FunctionDescriptor> getTestFunctionDescriptors(
|
||||||
@NotNull BindingContext bindingContext,
|
@NotNull ModuleDescriptor moduleDescriptor
|
||||||
@NotNull Collection<KtFile> files
|
|
||||||
) {
|
) {
|
||||||
List<FunctionDescriptor> answer = Lists.newArrayList();
|
List<FunctionDescriptor> answer = Lists.newArrayList();
|
||||||
for (KtFile file : files) {
|
getTestFunctions(FqName.ROOT, moduleDescriptor, answer);
|
||||||
answer.addAll(getTestFunctions(bindingContext, file.getDeclarations()));
|
|
||||||
}
|
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void getTestFunctions(
|
||||||
|
@NotNull FqName packageName,
|
||||||
|
@NotNull ModuleDescriptor moduleDescriptor,
|
||||||
|
@NotNull List<FunctionDescriptor> foundFunctions
|
||||||
|
) {
|
||||||
|
for (PackageFragmentDescriptor packageDescriptor : moduleDescriptor.getPackage(packageName).getFragments()) {
|
||||||
|
Collection<DeclarationDescriptor> descriptors = DescriptorUtils.getAllDescriptors(packageDescriptor.getMemberScope());
|
||||||
|
for (DeclarationDescriptor descriptor : descriptors) {
|
||||||
|
if (descriptor instanceof ClassDescriptor) {
|
||||||
|
getTestFunctions((ClassDescriptor) descriptor, foundFunctions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (FqName subpackageName : moduleDescriptor.getSubPackagesOf(packageName, MemberScope.Companion.getALL_NAME_FILTER())) {
|
||||||
|
getTestFunctions(subpackageName, moduleDescriptor, foundFunctions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static List<FunctionDescriptor> getTestFunctions(
|
private static void getTestFunctions(
|
||||||
@NotNull BindingContext bindingContext,
|
@NotNull ClassDescriptor classDescriptor,
|
||||||
@NotNull List<KtDeclaration> declarations
|
@NotNull List<FunctionDescriptor> foundFunctions
|
||||||
) {
|
) {
|
||||||
List<FunctionDescriptor> answer = Lists.newArrayList();
|
if (classDescriptor.getModality() == Modality.ABSTRACT) return;
|
||||||
for (KtDeclaration declaration : declarations) {
|
|
||||||
MemberScope scope = null;
|
|
||||||
|
|
||||||
if (declaration instanceof KtClass) {
|
|
||||||
KtClass klass = (KtClass) declaration;
|
|
||||||
ClassDescriptor classDescriptor = BindingUtils.getClassDescriptor(bindingContext, klass);
|
|
||||||
|
|
||||||
if (classDescriptor.getModality() != Modality.ABSTRACT) {
|
Collection<DeclarationDescriptor> allDescriptors = DescriptorUtils.getAllDescriptors(classDescriptor.getUnsubstitutedMemberScope());
|
||||||
scope = classDescriptor.getDefaultType().getMemberScope();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scope != null) {
|
|
||||||
Collection<DeclarationDescriptor> allDescriptors = DescriptorUtils.getAllDescriptors(scope);
|
|
||||||
List<FunctionDescriptor> testFunctions = ContainerUtil.mapNotNull(
|
List<FunctionDescriptor> testFunctions = ContainerUtil.mapNotNull(
|
||||||
allDescriptors,
|
allDescriptors,
|
||||||
descriptor -> {
|
descriptor-> {
|
||||||
if (descriptor instanceof FunctionDescriptor) {
|
if (descriptor instanceof FunctionDescriptor) {
|
||||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor;
|
||||||
if (isTest(functionDescriptor)) return functionDescriptor;
|
if (isTest(functionDescriptor)) return functionDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
foundFunctions.addAll(testFunctions);
|
||||||
|
|
||||||
answer.addAll(testFunctions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return answer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,14 @@ package org.jetbrains.kotlin.js.translate.general;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||||
import org.jetbrains.kotlin.idea.MainFunctionDetector;
|
import org.jetbrains.kotlin.idea.MainFunctionDetector;
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*;
|
import org.jetbrains.kotlin.js.backend.ast.*;
|
||||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||||
import org.jetbrains.kotlin.js.facade.MainCallParameters;
|
import org.jetbrains.kotlin.js.facade.MainCallParameters;
|
||||||
|
import org.jetbrains.kotlin.js.facade.TranslationUnit;
|
||||||
import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
|
import org.jetbrains.kotlin.js.facade.exceptions.TranslationException;
|
||||||
import org.jetbrains.kotlin.js.facade.exceptions.TranslationRuntimeException;
|
import org.jetbrains.kotlin.js.facade.exceptions.TranslationRuntimeException;
|
||||||
import org.jetbrains.kotlin.js.facade.exceptions.UnsupportedFeatureException;
|
import org.jetbrains.kotlin.js.facade.exceptions.UnsupportedFeatureException;
|
||||||
@@ -43,24 +45,25 @@ import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils;
|
|||||||
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
import org.jetbrains.kotlin.js.translate.utils.BindingUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||||
import org.jetbrains.kotlin.js.translate.utils.mutator.AssignToExpressionMutator;
|
import org.jetbrains.kotlin.js.translate.utils.mutator.AssignToExpressionMutator;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||||
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
|
import org.jetbrains.kotlin.psi.KtUnaryExpression;
|
||||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue;
|
||||||
import org.jetbrains.kotlin.resolve.constants.NullValue;
|
import org.jetbrains.kotlin.resolve.constants.NullValue;
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||||
|
import org.jetbrains.kotlin.serialization.js.ast.JsAstDeserializer;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
import org.jetbrains.kotlin.types.KotlinType;
|
||||||
import org.jetbrains.kotlin.types.TypeUtils;
|
import org.jetbrains.kotlin.types.TypeUtils;
|
||||||
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
import org.jetbrains.kotlin.utils.ExceptionUtilsKt;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.util.Collection;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.wrapIfNecessary;
|
import static org.jetbrains.kotlin.js.translate.general.ModuleWrapperTranslation.wrapIfNecessary;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.BindingUtils.getFunctionDescriptor;
|
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement;
|
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.convertToStatement;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.toStringLiteralList;
|
import static org.jetbrains.kotlin.js.translate.utils.JsAstUtils.toStringLiteralList;
|
||||||
import static org.jetbrains.kotlin.js.translate.utils.mutator.LastExpressionMutator.mutateLastExpression;
|
import static org.jetbrains.kotlin.js.translate.utils.mutator.LastExpressionMutator.mutateLastExpression;
|
||||||
@@ -236,13 +239,13 @@ public final class Translation {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static AstGenerationResult generateAst(
|
public static AstGenerationResult generateAst(
|
||||||
@NotNull BindingTrace bindingTrace,
|
@NotNull BindingTrace bindingTrace,
|
||||||
@NotNull Collection<KtFile> files,
|
@NotNull Collection<TranslationUnit> units,
|
||||||
@NotNull MainCallParameters mainCallParameters,
|
@NotNull MainCallParameters mainCallParameters,
|
||||||
@NotNull ModuleDescriptor moduleDescriptor,
|
@NotNull ModuleDescriptor moduleDescriptor,
|
||||||
@NotNull JsConfig config
|
@NotNull JsConfig config
|
||||||
) throws TranslationException {
|
) throws TranslationException {
|
||||||
try {
|
try {
|
||||||
return doGenerateAst(bindingTrace, files, mainCallParameters, moduleDescriptor, config);
|
return doGenerateAst(bindingTrace, units, mainCallParameters, moduleDescriptor, config);
|
||||||
}
|
}
|
||||||
catch (UnsupportedOperationException e) {
|
catch (UnsupportedOperationException e) {
|
||||||
throw new UnsupportedFeatureException("Unsupported feature used.", e);
|
throw new UnsupportedFeatureException("Unsupported feature used.", e);
|
||||||
@@ -255,7 +258,7 @@ public final class Translation {
|
|||||||
@NotNull
|
@NotNull
|
||||||
private static AstGenerationResult doGenerateAst(
|
private static AstGenerationResult doGenerateAst(
|
||||||
@NotNull BindingTrace bindingTrace,
|
@NotNull BindingTrace bindingTrace,
|
||||||
@NotNull Collection<KtFile> files,
|
@NotNull Collection<TranslationUnit> units,
|
||||||
@NotNull MainCallParameters mainCallParameters,
|
@NotNull MainCallParameters mainCallParameters,
|
||||||
@NotNull ModuleDescriptor moduleDescriptor,
|
@NotNull ModuleDescriptor moduleDescriptor,
|
||||||
@NotNull JsConfig config
|
@NotNull JsConfig config
|
||||||
@@ -265,23 +268,40 @@ public final class Translation {
|
|||||||
JsName internalModuleName = program.getScope().declareName("_");
|
JsName internalModuleName = program.getScope().declareName("_");
|
||||||
Merger merger = new Merger(rootFunction, internalModuleName, moduleDescriptor);
|
Merger merger = new Merger(rootFunction, internalModuleName, moduleDescriptor);
|
||||||
|
|
||||||
|
Map<KtFile, JsProgramFragment> fragmentMap = new HashMap<KtFile, JsProgramFragment>();
|
||||||
List<JsProgramFragment> fragments = new ArrayList<JsProgramFragment>();
|
List<JsProgramFragment> fragments = new ArrayList<JsProgramFragment>();
|
||||||
for (KtFile file : files) {
|
|
||||||
StaticContext staticContext = new StaticContext(bindingTrace, config, moduleDescriptor);
|
Map<KtFile, List<DeclarationDescriptor>> fileMemberScopes = new HashMap<KtFile, List<DeclarationDescriptor>>();
|
||||||
TranslationContext context = TranslationContext.rootContext(staticContext);
|
|
||||||
translateFile(context, file);
|
JsAstDeserializer deserializer = new JsAstDeserializer(program);
|
||||||
fragments.add(staticContext.getFragment());
|
for (TranslationUnit unit : units) {
|
||||||
merger.addFragment(staticContext.getFragment());
|
if (unit instanceof TranslationUnit.SourceFile) {
|
||||||
|
KtFile file = ((TranslationUnit.SourceFile) unit).getFile();
|
||||||
|
StaticContext staticContext = new StaticContext(bindingTrace, config, moduleDescriptor);
|
||||||
|
TranslationContext context = TranslationContext.rootContext(staticContext);
|
||||||
|
List<DeclarationDescriptor> fileMemberScope = new ArrayList<DeclarationDescriptor>();
|
||||||
|
translateFile(context, file, fileMemberScope);
|
||||||
|
fragments.add(staticContext.getFragment());
|
||||||
|
fragmentMap.put(file, staticContext.getFragment());
|
||||||
|
fileMemberScopes.put(file, fileMemberScope);
|
||||||
|
merger.addFragment(staticContext.getFragment());
|
||||||
|
}
|
||||||
|
else if (unit instanceof TranslationUnit.BinaryAst) {
|
||||||
|
byte[] astData = ((TranslationUnit.BinaryAst) unit).getData();
|
||||||
|
JsProgramFragment fragment = deserializer.deserialize(new ByteArrayInputStream(astData));
|
||||||
|
merger.addFragment(fragment);
|
||||||
|
fragments.add(fragment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JsProgramFragment testFragment = mayBeGenerateTests(files, config, bindingTrace, moduleDescriptor);
|
JsProgramFragment testFragment = mayBeGenerateTests(config, bindingTrace, moduleDescriptor);
|
||||||
fragments.add(testFragment);
|
fragments.add(testFragment);
|
||||||
merger.addFragment(testFragment);
|
merger.addFragment(testFragment);
|
||||||
rootFunction.getParameters().add(new JsParameter(internalModuleName));
|
rootFunction.getParameters().add(new JsParameter(internalModuleName));
|
||||||
|
|
||||||
if (mainCallParameters.shouldBeGenerated()) {
|
if (mainCallParameters.shouldBeGenerated()) {
|
||||||
JsProgramFragment mainCallFragment = generateCallToMain(
|
JsProgramFragment mainCallFragment = generateCallToMain(
|
||||||
bindingTrace, config, moduleDescriptor, files, mainCallParameters.arguments());
|
bindingTrace, config, moduleDescriptor, mainCallParameters.arguments());
|
||||||
if (mainCallFragment != null) {
|
if (mainCallFragment != null) {
|
||||||
fragments.add(mainCallFragment);
|
fragments.add(mainCallFragment);
|
||||||
merger.addFragment(mainCallFragment);
|
merger.addFragment(mainCallFragment);
|
||||||
@@ -313,7 +333,7 @@ public final class Translation {
|
|||||||
block.getStatements().addAll(wrapIfNecessary(config.getModuleId(), rootFunction, importedModuleList, program,
|
block.getStatements().addAll(wrapIfNecessary(config.getModuleId(), rootFunction, importedModuleList, program,
|
||||||
config.getModuleKind()));
|
config.getModuleKind()));
|
||||||
|
|
||||||
return new AstGenerationResult(program, internalModuleName, fragments, importedModuleList);
|
return new AstGenerationResult(program, internalModuleName, fragments, fragmentMap, fileMemberScopes, importedModuleList);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isBuiltinModule(@NotNull List<JsProgramFragment> fragments) {
|
private static boolean isBuiltinModule(@NotNull List<JsProgramFragment> fragments) {
|
||||||
@@ -327,12 +347,18 @@ public final class Translation {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void translateFile(@NotNull TranslationContext context, @NotNull KtFile file) {
|
private static void translateFile(
|
||||||
|
@NotNull TranslationContext context,
|
||||||
|
@NotNull KtFile file,
|
||||||
|
@NotNull List<DeclarationDescriptor> fileMemberScope
|
||||||
|
) {
|
||||||
FileDeclarationVisitor fileVisitor = new FileDeclarationVisitor(context);
|
FileDeclarationVisitor fileVisitor = new FileDeclarationVisitor(context);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (KtDeclaration declaration : file.getDeclarations()) {
|
for (KtDeclaration declaration : file.getDeclarations()) {
|
||||||
if (!AnnotationsUtils.isPredefinedObject(BindingUtils.getDescriptorForElement(context.bindingContext(), declaration))) {
|
DeclarationDescriptor descriptor = BindingUtils.getDescriptorForElement(context.bindingContext(), declaration);
|
||||||
|
fileMemberScope.add(descriptor);
|
||||||
|
if (!AnnotationsUtils.isPredefinedObject(descriptor)) {
|
||||||
declaration.accept(fileVisitor, context);
|
declaration.accept(fileVisitor, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -359,13 +385,13 @@ public final class Translation {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private static JsProgramFragment mayBeGenerateTests(
|
private static JsProgramFragment mayBeGenerateTests(
|
||||||
@NotNull Collection<KtFile> files, @NotNull JsConfig config, @NotNull BindingTrace trace,
|
@NotNull JsConfig config, @NotNull BindingTrace trace,
|
||||||
@NotNull ModuleDescriptor moduleDescriptor
|
@NotNull ModuleDescriptor moduleDescriptor
|
||||||
) {
|
) {
|
||||||
StaticContext staticContext = new StaticContext(trace, config, moduleDescriptor);
|
StaticContext staticContext = new StaticContext(trace, config, moduleDescriptor);
|
||||||
TranslationContext context = TranslationContext.rootContext(staticContext);
|
TranslationContext context = TranslationContext.rootContext(staticContext);
|
||||||
JSTester tester = new QUnitTester(context);
|
JSTester tester = new QUnitTester(context);
|
||||||
JSTestGenerator.generateTestCalls(context, files, tester);
|
JSTestGenerator.generateTestCalls(context, moduleDescriptor, tester);
|
||||||
|
|
||||||
return staticContext.getFragment();
|
return staticContext.getFragment();
|
||||||
}
|
}
|
||||||
@@ -374,16 +400,15 @@ public final class Translation {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private static JsProgramFragment generateCallToMain(
|
private static JsProgramFragment generateCallToMain(
|
||||||
@NotNull BindingTrace trace, @NotNull JsConfig config, @NotNull ModuleDescriptor moduleDescriptor,
|
@NotNull BindingTrace trace, @NotNull JsConfig config, @NotNull ModuleDescriptor moduleDescriptor,
|
||||||
@NotNull Collection<KtFile> files, @NotNull List<String> arguments
|
@NotNull List<String> arguments
|
||||||
) {
|
) {
|
||||||
StaticContext staticContext = new StaticContext(trace, config, moduleDescriptor);
|
StaticContext staticContext = new StaticContext(trace, config, moduleDescriptor);
|
||||||
TranslationContext context = TranslationContext.rootContext(staticContext);
|
TranslationContext context = TranslationContext.rootContext(staticContext);
|
||||||
MainFunctionDetector mainFunctionDetector = new MainFunctionDetector(context.bindingContext());
|
MainFunctionDetector mainFunctionDetector = new MainFunctionDetector(context.bindingContext());
|
||||||
KtNamedFunction mainFunction = mainFunctionDetector.getMainFunction(files);
|
FunctionDescriptor functionDescriptor = mainFunctionDetector.getMainFunction(moduleDescriptor);
|
||||||
if (mainFunction == null) {
|
if (functionDescriptor == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
FunctionDescriptor functionDescriptor = getFunctionDescriptor(context.bindingContext(), mainFunction);
|
|
||||||
JsArrayLiteral argument = new JsArrayLiteral(toStringLiteralList(arguments, context.program()));
|
JsArrayLiteral argument = new JsArrayLiteral(toStringLiteralList(arguments, context.program()));
|
||||||
JsExpression call = CallTranslator.INSTANCE.buildCall(context, functionDescriptor, Collections.singletonList(argument), null);
|
JsExpression call = CallTranslator.INSTANCE.buildCall(context, functionDescriptor, Collections.singletonList(argument), null);
|
||||||
context.addTopLevelStatement(call.makeStmt());
|
context.addTopLevelStatement(call.makeStmt());
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.js.translate.test;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
|
import org.jetbrains.kotlin.js.backend.ast.JsExpression;
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsNew;
|
import org.jetbrains.kotlin.js.backend.ast.JsNew;
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsStringLiteral;
|
import org.jetbrains.kotlin.js.backend.ast.JsStringLiteral;
|
||||||
@@ -26,10 +27,8 @@ import org.jetbrains.kotlin.js.translate.callTranslator.CallTranslator;
|
|||||||
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
import org.jetbrains.kotlin.js.translate.context.TranslationContext;
|
||||||
import org.jetbrains.kotlin.js.translate.general.JetTestFunctionDetector;
|
import org.jetbrains.kotlin.js.translate.general.JetTestFunctionDetector;
|
||||||
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator;
|
import org.jetbrains.kotlin.js.translate.reference.ReferenceTranslator;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -39,8 +38,9 @@ public final class JSTestGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void generateTestCalls(@NotNull TranslationContext context,
|
public static void generateTestCalls(@NotNull TranslationContext context,
|
||||||
@NotNull Collection<KtFile> files, @NotNull JSTester tester) {
|
@NotNull ModuleDescriptor moduleDescriptor, @NotNull JSTester tester) {
|
||||||
List<FunctionDescriptor> functionDescriptors = JetTestFunctionDetector.getTestFunctionDescriptors(context.bindingContext(), files);
|
List<FunctionDescriptor> functionDescriptors =
|
||||||
|
JetTestFunctionDetector.getTestFunctionDescriptors(moduleDescriptor);
|
||||||
doGenerateTestCalls(functionDescriptors, context, tester);
|
doGenerateTestCalls(functionDescriptors, context, tester);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// FILE: a.kt
|
||||||
|
|
||||||
|
private fun bar(): String = "O"
|
||||||
|
|
||||||
|
internal fun foo(): String = bar()
|
||||||
|
|
||||||
|
fun baz(): String = "K"
|
||||||
|
|
||||||
|
// FILE: b.kt
|
||||||
|
// RECOMPILE
|
||||||
|
|
||||||
|
fun box(): String = foo() + baz()
|
||||||
Reference in New Issue
Block a user