diff --git a/build.gradle.kts b/build.gradle.kts index f7e155a34..aaf129806 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.springframework.boot.gradle.tasks.bundling.BootJar -val kotlinVersion: String by System.getProperties() +val kotlinVersion = rootProject.properties["systemProp.kotlinVersion"] val kotlinIdeVersion: String by System.getProperties() val kotlinIdeVersionSuffix: String by System.getProperties() val policy: String by System.getProperties() @@ -54,12 +54,12 @@ val copyDependencies by tasks.creating(Copy::class) { into(libJVMFolder) } val copyJSDependencies by tasks.creating(Copy::class) { - from(files(Callable { kotlinJsDependency.map { zipTree(it) } })) + from(kotlinJsDependency) into(libJSFolder) } val copyWasmDependencies by tasks.creating(Copy::class) { - from(files(Callable { kotlinWasmDependency.map { zipTree(it) } })) + from(kotlinWasmDependency) into(libWasmFolder) } @@ -73,7 +73,9 @@ plugins { apply() -the().nodeVersion = "20.2.0" +// for new Wasm opcodes +the().nodeVersion = "21.0.0-v8-canary202309167e82ab1fa2" +the().nodeDownloadBaseUrl = "https://nodejs.org/download/v8-canary" allprojects { repositories { @@ -82,6 +84,7 @@ allprojects { maven("https://repo.spring.io/snapshot") maven("https://repo.spring.io/milestone") maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide") + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev") maven("https://cache-redirector.jetbrains.com/jetbrains.bintray.com/intellij-third-party-dependencies") maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-ide-plugin-dependencies") maven("https://www.myget.org/F/rd-snapshots/maven/") @@ -113,7 +116,8 @@ dependencies { kotlinDependency("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") kotlinDependency("org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.7.3") kotlinJsDependency("org.jetbrains.kotlin:kotlin-stdlib-js:$kotlinVersion") - kotlinWasmDependency("org.jetbrains.kotlin:kotlin-stdlib-wasm:$kotlinVersion") + kotlinJsDependency("org.jetbrains.kotlin:kotlin-dom-api-compat:$kotlinVersion") + kotlinWasmDependency("org.jetbrains.kotlin:kotlin-stdlib-wasm-js:$kotlinVersion") annotationProcessor("org.springframework:spring-context-indexer") implementation("com.google.code.gson:gson") @@ -129,7 +133,6 @@ dependencies { implementation("org.jetbrains.kotlin:kotlin-test:$kotlinVersion") implementation("org.jetbrains.kotlin:kotlin-compiler:$kotlinVersion") implementation("org.jetbrains.kotlin:kotlin-script-runtime:$kotlinVersion") - implementation("org.jetbrains.kotlin:kotlin-stdlib-js:$kotlinVersion") implementation("org.jetbrains.kotlin:kotlin-compiler-for-ide:$kotlinIdeVersion"){ isTransitive = false } @@ -183,6 +186,7 @@ tasks.withType { dependsOn(":indexation:run") buildPropertyFile() } +println("Using Kotlin compiler $kotlinVersion") tasks.withType { requiresUnpack("**/kotlin-*.jar") diff --git a/gradle.properties b/gradle.properties index d7fd4cf1c..7ab61d986 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ -systemProp.kotlinVersion=1.9.10 -systemProp.kotlinIdeVersion=1.9.10-456 -systemProp.kotlinIdeVersionSuffix=IJ8770.65 +systemProp.kotlinVersion=1.9.20-Beta2 +systemProp.kotlinIdeVersion=1.9.20-Beta-224 +systemProp.kotlinIdeVersionSuffix=IJ8109.175 systemProp.policy=executor.policy systemProp.indexes=indexes.json systemProp.indexesJs=indexesJs.json diff --git a/indexation/src/main/kotlin/JsIndexationBuilder.kt b/indexation/src/main/kotlin/JsIndexationBuilder.kt index 42b3abc82..b54f8ab06 100644 --- a/indexation/src/main/kotlin/JsIndexationBuilder.kt +++ b/indexation/src/main/kotlin/JsIndexationBuilder.kt @@ -2,6 +2,8 @@ package indexation import model.ImportInfo import component.KotlinEnvironment +import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport +import org.jetbrains.kotlin.ir.backend.js.prepareAnalyzedSourceModule import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.resolve.CompilerEnvironment @@ -9,15 +11,21 @@ class JsIndexationBuilder(private val kotlinEnvironment: KotlinEnvironment): Ind override fun getAllIndexes(): List = kotlinEnvironment.environment { coreEnvironment -> val project = coreEnvironment.project - val configuration = JsConfig( + + val sourceModule = prepareAnalyzedSourceModule( project, + coreEnvironment.getSourceFiles(), kotlinEnvironment.jsConfiguration, - CompilerEnvironment, - kotlinEnvironment.JS_METADATA_CACHE, - kotlinEnvironment.JS_LIBRARIES.toSet() + kotlinEnvironment.JS_LIBRARIES, + friendDependencies = emptyList(), + analyzer = AnalyzerWithCompilerReport(kotlinEnvironment.jsConfiguration), ) - return@environment configuration.moduleDescriptors.flatMap { moduleDescriptor -> + val mds = sourceModule.allDependencies.map { + sourceModule.getModuleDescriptor(it) + } + + return@environment mds.flatMap { moduleDescriptor -> moduleDescriptor.allImportsInfo() }.distinct() } diff --git a/indexation/src/main/kotlin/KotlinEnvironmentConfiguration.kt b/indexation/src/main/kotlin/KotlinEnvironmentConfiguration.kt index 3ae0136dd..c56ef4ff1 100644 --- a/indexation/src/main/kotlin/KotlinEnvironmentConfiguration.kt +++ b/indexation/src/main/kotlin/KotlinEnvironmentConfiguration.kt @@ -15,7 +15,9 @@ class KotlinEnvironmentConfiguration(fileName: String) { ?: error("No kotlin libraries found in: ${jvmFile.absolutePath}") } - val additionalJsClasspath = listOfNotNull(jsFile) - KotlinEnvironment(classPath, additionalJsClasspath, listOfNotNull(wasmFile)) + val additionalJsClasspath = jsFile.listFiles()?.toList() ?: emptyList() + val additionalWasmClasspath = wasmFile.listFiles()?.toList() ?: emptyList() + + KotlinEnvironment(classPath, additionalJsClasspath, additionalWasmClasspath) } } diff --git a/src/main/kotlin/com/compiler/server/compiler/components/ErrorAnalyzer.kt b/src/main/kotlin/com/compiler/server/compiler/components/ErrorAnalyzer.kt index 149ee924c..62238ecde 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/ErrorAnalyzer.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/ErrorAnalyzer.kt @@ -12,6 +12,8 @@ import com.intellij.psi.PsiFile import component.KotlinEnvironment import model.Completion import org.jetbrains.kotlin.analyzer.AnalysisResult +import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport +import org.jetbrains.kotlin.cli.js.klib.TopDownAnalyzerFacadeForJSIR import org.jetbrains.kotlin.cli.jvm.compiler.CliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM @@ -29,7 +31,9 @@ import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.frontend.di.configureModule import org.jetbrains.kotlin.incremental.components.InlineConstTracker import org.jetbrains.kotlin.incremental.components.LookupTracker -import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS +import org.jetbrains.kotlin.ir.backend.js.MainModule +import org.jetbrains.kotlin.ir.backend.js.ModulesStructure +import org.jetbrains.kotlin.ir.backend.js.prepareAnalyzedSourceModule import org.jetbrains.kotlin.js.config.JsConfig import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices import org.jetbrains.kotlin.name.Name @@ -111,18 +115,41 @@ class ErrorAnalyzer( kotlinEnvironment.JS_LIBRARIES.toSet() ) - val module = ContextForNewModule( + val mainModule = MainModule.SourceFiles(files) + val sourceModule = ModulesStructure( + project, + mainModule, + kotlinEnvironment.jsConfiguration, + kotlinEnvironment.JS_LIBRARIES, + emptyList() + ) + + val mds = sourceModule.allDependencies.map { + sourceModule.getModuleDescriptor(it) as ModuleDescriptorImpl + } + + val analysisResult = TopDownAnalyzerFacadeForJSIR.analyzeFiles( + mainModule.files, + project, + kotlinEnvironment.jsConfiguration, + mds, + emptyList(), + AnalyzerWithCompilerReport(kotlinEnvironment.jsConfiguration).targetEnvironment + ) + + val context = ContextForNewModule( projectContext = ProjectContext(project, "COMPILER-SERVER-JS"), moduleName = Name.special("<" + configuration.moduleId + ">"), builtIns = JsPlatformAnalyzerServices.builtIns, platform = null ) - module.setDependencies(computeDependencies(module.module, configuration)) + val dependencies = mutableSetOf(context.module) + mds + JsPlatformAnalyzerServices.builtIns.builtInsModule + context.module.setDependencies(dependencies.toList()) val trace = CliBindingTrace() - val providerFactory = FileBasedDeclarationProviderFactory(module.storageManager, files) - val analyzerAndProvider = createContainerForTopDownAnalyzerForJs(module, trace, providerFactory) + val providerFactory = FileBasedDeclarationProviderFactory(context.storageManager, files) + val analyzerAndProvider = createContainerForTopDownAnalyzerForJs(context, trace, providerFactory) return Analysis( componentProvider = analyzerAndProvider.second, - analysisResult = TopDownAnalyzerFacadeForJS.analyzeFiles(files, configuration) + analysisResult = analysisResult ) } diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt index 96e11e57b..7e9153e5f 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinEnvironment.kt @@ -16,7 +16,9 @@ class KotlinEnvironmentConfiguration(val librariesFile: LibrariesFile) { ?: error("No kotlin libraries found in: ${librariesFile.jvm.absolutePath}") } - val additionalJsClasspath = listOfNotNull(librariesFile.js) - return KotlinEnvironment(classPath, additionalJsClasspath, listOfNotNull(librariesFile.wasm)) + val additionalJsClasspath = librariesFile.js.listFiles()?.toList() ?: emptyList() + val additionalWasmClasspath = librariesFile.wasm.listFiles()?.toList() ?: emptyList() + + return KotlinEnvironment(classPath, additionalJsClasspath, additionalWasmClasspath) } } diff --git a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt index 0c3c506e0..c51fc620f 100644 --- a/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt +++ b/src/main/kotlin/com/compiler/server/compiler/components/KotlinToJSTranslator.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.wasm.wasmPhases import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.ir.backend.js.* +import org.jetbrains.kotlin.ir.backend.js.dce.DceDumpNameCache import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.TranslationMode import org.jetbrains.kotlin.ir.declarations.impl.IrFactoryImpl @@ -168,7 +169,7 @@ class KotlinToJSTranslator( exportedDeclarations = setOf(FqName("main")), propertyLazyInitialization = true, ) - eliminateDeadDeclarations(allModules, backendContext) + eliminateDeadDeclarations(allModules, backendContext, DceDumpNameCache()) val res = compileWasm( allModules = allModules, diff --git a/src/main/kotlin/com/compiler/server/controllers/CompilerRestController.kt b/src/main/kotlin/com/compiler/server/controllers/CompilerRestController.kt index a9b59d0f3..dd730cbc4 100644 --- a/src/main/kotlin/com/compiler/server/controllers/CompilerRestController.kt +++ b/src/main/kotlin/com/compiler/server/controllers/CompilerRestController.kt @@ -21,12 +21,8 @@ class CompilerRestController(private val kotlinProjectExecutor: KotlinProjectExe @PostMapping("/translate") fun translateKotlinProjectEndpoint( @RequestBody project: Project, - @RequestParam(defaultValue = "false") ir: Boolean, @RequestParam(defaultValue = "js") compiler: String ): TranslationResultWithJsCode { - if (!ir) { - return kotlinProjectExecutor.convertToJs(project) - } return when (KotlinTranslatableCompiler.valueOf(compiler.uppercase())) { KotlinTranslatableCompiler.JS -> kotlinProjectExecutor.convertToJsIr(project) KotlinTranslatableCompiler.WASM -> kotlinProjectExecutor.convertToWasm(project) diff --git a/src/main/kotlin/com/compiler/server/controllers/KotlinPlaygroundRestController.kt b/src/main/kotlin/com/compiler/server/controllers/KotlinPlaygroundRestController.kt index db678af7f..5dffbdf1d 100644 --- a/src/main/kotlin/com/compiler/server/controllers/KotlinPlaygroundRestController.kt +++ b/src/main/kotlin/com/compiler/server/controllers/KotlinPlaygroundRestController.kt @@ -1,5 +1,6 @@ package com.compiler.server.controllers +import com.compiler.server.exceptions.LegacyJsException import com.compiler.server.model.Project import com.compiler.server.model.ProjectType import com.compiler.server.service.KotlinProjectExecutor @@ -39,7 +40,7 @@ class KotlinPlaygroundRestController(private val kotlinProjectExecutor: KotlinPr "run" -> { when (project.confType) { ProjectType.JAVA -> kotlinProjectExecutor.run(project) - ProjectType.JS, ProjectType.CANVAS -> kotlinProjectExecutor.convertToJs(project) + ProjectType.JS, ProjectType.CANVAS -> throw LegacyJsException() ProjectType.JS_IR -> kotlinProjectExecutor.convertToJsIr(project) ProjectType.WASM -> kotlinProjectExecutor.convertToWasm(project) ProjectType.JUNIT -> kotlinProjectExecutor.test(project) diff --git a/src/main/kotlin/com/compiler/server/exceptions/LegacyJsException.kt b/src/main/kotlin/com/compiler/server/exceptions/LegacyJsException.kt new file mode 100644 index 000000000..170f31d66 --- /dev/null +++ b/src/main/kotlin/com/compiler/server/exceptions/LegacyJsException.kt @@ -0,0 +1,7 @@ +package com.compiler.server.exceptions + +import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.ResponseStatus + +@ResponseStatus(value = HttpStatus.BAD_REQUEST) +class LegacyJsException : RuntimeException() \ No newline at end of file diff --git a/src/test/kotlin/com/compiler/server/CommandLineArgumentsTest.kt b/src/test/kotlin/com/compiler/server/CommandLineArgumentsTest.kt index c4447ce92..ce8d21afc 100644 --- a/src/test/kotlin/com/compiler/server/CommandLineArgumentsTest.kt +++ b/src/test/kotlin/com/compiler/server/CommandLineArgumentsTest.kt @@ -23,15 +23,6 @@ class CommandLineArgumentsTest : BaseExecutorTest() { ) } - @Test - fun `command line arguments js test`() { - runJs( - code = "fun main(args: Array) {\n println(args[0])\n println(args[1])\n}", - args = "0 1", - contains = "main(['0', '1']);" - ) - } - @Test fun `command line arguments js ir test`() { runJsIr( @@ -41,15 +32,6 @@ class CommandLineArgumentsTest : BaseExecutorTest() { ) } - @Test - fun `command line string arguments js test`() { - runJs( - code = "fun main(args: Array) {\n println(args[0])\n println(args[1])\n}", - args = "alex1 alex2", - contains = "main(['alex1', 'alex2']);" - ) - } - @Test fun `command line string arguments js ir test`() { runJsIr( diff --git a/src/test/kotlin/com/compiler/server/ConvertToJsRunnerTest.kt b/src/test/kotlin/com/compiler/server/ConvertToJsRunnerTest.kt index fbf9b25ae..3ab5567d8 100644 --- a/src/test/kotlin/com/compiler/server/ConvertToJsRunnerTest.kt +++ b/src/test/kotlin/com/compiler/server/ConvertToJsRunnerTest.kt @@ -3,36 +3,6 @@ package com.compiler.server import com.compiler.server.base.BaseExecutorTest import org.junit.jupiter.api.Test -class ConvertToJsRunnerTest : BaseExecutorTest() { - - @Test - fun `base execute test`() { - runJs( - code = "fun main() {\n println(\"Hello, world!!!\")\n}", - contains = "println('Hello, world!!!');" - ) - } - - @Test - fun `base execute test multi`() { - runJs( - code = listOf( - "import cat.Cat\n\nfun main(args: Array) {\nval cat = Cat(\"Kitty\")\nprintln(cat.name)\n}", - "package cat\n class Cat(val name: String)" - ), - contains = "var cat = new Cat('Kitty');" - ) - } - - @Test - fun `canvas with jquery test`() { - runJs( - code = "package fancylines\n\n\nimport org.w3c.dom.CanvasRenderingContext2D\nimport org.w3c.dom.HTMLCanvasElement\nimport kotlinx.browser.document\nimport kotlinx.browser.window\nimport kotlin.random.Random\n\n\n\nval canvas = initalizeCanvas()\nfun initalizeCanvas(): HTMLCanvasElement {\n val canvas = document.createElement(\"canvas\") as HTMLCanvasElement\n val context = canvas.getContext(\"2d\") as CanvasRenderingContext2D\n context.canvas.width = window.innerWidth.toInt();\n context.canvas.height = window.innerHeight.toInt();\n document.body!!.appendChild(canvas)\n return canvas\n}\n\nclass FancyLines() {\n val context = canvas.getContext(\"2d\") as CanvasRenderingContext2D\n val height = canvas.height\n val width = canvas.width\n var x = width * Random.nextDouble()\n var y = height * Random.nextDouble()\n var hue = 0;\n\n fun line() {\n context.save();\n\n context.beginPath();\n\n context.lineWidth = 20.0 * Random.nextDouble();\n context.moveTo(x, y);\n\n x = width * Random.nextDouble();\n y = height * Random.nextDouble();\n\n context.bezierCurveTo(width * Random.nextDouble(), height * Random.nextDouble(),\n width * Random.nextDouble(), height * Random.nextDouble(), x, y);\n\n hue += (Random.nextDouble() * 10).toInt();\n\n context.strokeStyle = \"hsl(\$hue, 50%, 50%)\";\n\n context.shadowColor = \"white\";\n context.shadowBlur = 10.0;\n\n context.stroke();\n\n context.restore();\n }\n\n fun blank() {\n context.fillStyle = \"rgba(255,255,1,0.1)\";\n context.fillRect(0.0, 0.0, width.toDouble(), height.toDouble());\n }\n\n fun run() {\n window.setInterval({ line() }, 40);\n window.setInterval({ blank() }, 100);\n }\n}\nfun main(args: Array) {\n FancyLines().run()\n}", - contains = "this.context = Kotlin.isType(tmp\$ = canvas.getContext('2d'), CanvasRenderingContext2D) ? tmp\$ : throwCCE();", - ) - } -} - class ConvertToJsIrRunnerTest : BaseExecutorTest() { @Test fun `base execute test`() { diff --git a/src/test/kotlin/com/compiler/server/generator/TestProjectRunner.kt b/src/test/kotlin/com/compiler/server/generator/TestProjectRunner.kt index 28b687fa0..0dd8cf822 100644 --- a/src/test/kotlin/com/compiler/server/generator/TestProjectRunner.kt +++ b/src/test/kotlin/com/compiler/server/generator/TestProjectRunner.kt @@ -34,7 +34,7 @@ class TestProjectRunner { args: String = "", convert: KotlinProjectExecutor.(Project) -> TranslationResultWithJsCode ) { - val project = generateSingleProject(text = code, args = args, projectType = ProjectType.JS) + val project = generateSingleProject(text = code, args = args, projectType = ProjectType.JS_IR) convertAndTest(project, contains, convert) } @@ -43,7 +43,7 @@ class TestProjectRunner { contains: String, convert: KotlinProjectExecutor.(Project) -> TranslationResultWithJsCode ) { - val project = generateMultiProject(*code.toTypedArray(), projectType = ProjectType.JS) + val project = generateMultiProject(*code.toTypedArray(), projectType = ProjectType.JS_IR) convertAndTest(project, contains, convert) } @@ -56,7 +56,7 @@ class TestProjectRunner { } fun translateToJs(code: String): TranslationResultWithJsCode { - val project = generateSingleProject(text = code, projectType = ProjectType.JS) + val project = generateSingleProject(text = code, projectType = ProjectType.JS_IR) return kotlinProjectExecutor.convertToJs(project) } @@ -87,7 +87,7 @@ class TestProjectRunner { completions: List, isJs: Boolean = false ) { - val type = if (isJs) ProjectType.JS else ProjectType.JAVA + val type = if (isJs) ProjectType.JS_IR else ProjectType.JAVA val project = generateSingleProject(text = code, projectType = type) val result = kotlinProjectExecutor.complete(project, line, character) .map { it.displayText } @@ -103,7 +103,7 @@ class TestProjectRunner { character: Int, isJs: Boolean = false ): List { - val type = if (isJs) ProjectType.JS else ProjectType.JAVA + val type = if (isJs) ProjectType.JS_IR else ProjectType.JAVA val project = generateSingleProject(text = code, projectType = type) return kotlinProjectExecutor.complete(project, line, character) } @@ -114,7 +114,7 @@ class TestProjectRunner { } fun highlightJS(code: String): Map> { - val project = generateSingleProject(text = code, projectType = ProjectType.JS) + val project = generateSingleProject(text = code, projectType = ProjectType.JS_IR) return kotlinProjectExecutor.highlight(project) } diff --git a/versions.json b/versions.json index bfca0b4c4..bd8e635dd 100644 --- a/versions.json +++ b/versions.json @@ -25,6 +25,6 @@ "latestStable": true }, { - "version": "1.9.20-Beta" + "version": "1.9.20-Beta2" } ]