Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 3 additions & 1 deletion common/src/main/kotlin/component/KotlinEnvironment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ class KotlinEnvironment(
"-opt-in=kotlin.contracts.ExperimentalContracts",
"-opt-in=kotlin.experimental.ExperimentalTypeInference",
"-Xcontext-receivers",
"-XXLanguage:+ExplicitBackingFields"
"-Xreport-all-warnings",
"-Xuse-fir-extended-checkers",
"-XXLanguage:+ExplicitBackingFields",
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.*
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.psi.KtFile
import java.io.File
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
import kotlin.io.path.*

Expand Down Expand Up @@ -126,7 +126,7 @@ fun <T> usingTempDirectory(action: (path: Path) -> T): T {
private fun getTempDirectory(): Path {
val dir = System.getProperty("java.io.tmpdir")
val sessionId = UUID.randomUUID().toString().replace("-", "")
return Paths.get(dir, sessionId)
return File(dir).canonicalFile.resolve(sessionId).toPath()
}

fun List<KtFile>.writeToIoFiles(inputDir: Path): List<Path> {
Expand All @@ -137,4 +137,4 @@ fun List<KtFile>.writeToIoFiles(inputDir: Path): List<Path> {
return ioFiles
}

val PATH_SEPARATOR: String = java.io.File.pathSeparator
val PATH_SEPARATOR: String = File.pathSeparator
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ class KotlinToJSTranslator(
val filePaths = ioFiles.map { it.toFile().canonicalPath }
val klibPath = (outputDir / "klib").toFile().canonicalPath
val additionalCompilerArgumentsForKLib = listOf(
"-Xreport-all-warnings",
"-Xuse-fir-extended-checkers",
"-Xir-only",
"-Xir-produce-klib-dir",
"-libraries=${kotlinEnvironment.JS_LIBRARIES.joinToString(PATH_SEPARATOR)}",
Expand All @@ -103,6 +105,8 @@ class KotlinToJSTranslator(
k2JsIrCompiler.tryCompilation(inputDir, ioFiles, filePaths + additionalCompilerArgumentsForKLib)
.flatMap {
k2JsIrCompiler.tryCompilation(inputDir, ioFiles, listOf(
"-Xreport-all-warnings",
"-Xuse-fir-extended-checkers",
"-Xir-only",
"-Xir-produce-js",
"-Xir-dce",
Expand Down Expand Up @@ -152,6 +156,8 @@ class KotlinToJSTranslator(
}
} ?: emptyList()
val additionalCompilerArgumentsForKLib: List<String> = listOf(
"-Xreport-all-warnings",
"-Xuse-fir-extended-checkers",
"-Xwasm",
"-Xir-produce-klib-dir",
"-libraries=${dependencies.joinToString(PATH_SEPARATOR)}",
Expand All @@ -162,6 +168,8 @@ class KotlinToJSTranslator(
k2JsIrCompiler.tryCompilation(inputDir, ioFiles, filePaths + additionalCompilerArgumentsForKLib)
.flatMap {
k2JsIrCompiler.tryCompilation(inputDir, ioFiles, listOf(
"-Xreport-all-warnings",
"-Xuse-fir-extended-checkers",
"-Xwasm",
"-Xwasm-generate-wat",
"-Xir-produce-js",
Expand Down
13 changes: 6 additions & 7 deletions src/test/kotlin/com/compiler/server/HighlightTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import com.compiler.server.base.BaseExecutorTest
import com.compiler.server.base.errorContains
import com.compiler.server.base.warningContains
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test

class HighlightTest : BaseExecutorTest() {
Expand All @@ -27,22 +26,22 @@ class HighlightTest : BaseExecutorTest() {
Assertions.assertTrue(highlights.isEmpty())
}

@Test @Disabled
@Test
fun `base highlight unused variable`() {
val highlights = highlight("fun main() {\n\tval a = \"d\"\n}")
warningContains(highlights, "Variable 'a' is never used")
warningContains(highlights, "Variable is unused")
}

@Test @Disabled
@Test
fun `base highlight unused variable js`() {
val highlights = highlightJS("fun main() {\n\tval a = \"d\"\n}")
warningContains(highlights, "Variable 'a' is never used")
warningContains(highlights, "Variable is unused")
}

@Test @Disabled
@Test
fun `base highlight unused variable wasm`() {
val highlights = highlightWasm("fun main() {\n\tval a = \"d\"\n}")
warningContains(highlights, "Variable 'a' is never used")
warningContains(highlights, "Variable is unused")
}

@Test
Expand Down
29 changes: 29 additions & 0 deletions src/test/kotlin/com/compiler/server/JvmRunnerTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,33 @@ class JvmRunnerTest : BaseExecutorTest() {
result.compilerDiagnostics[0].message
)
}

@Test
fun `warnings after exception`() {
// language=kotlin
val result = run(
"""
fun main() {
println("")g
var someVar = 1
}
""".trimIndent(), ""
)

assertContains(result.compilerDiagnostics.map { it.message }, "Variable is unused.")
}

@Test
fun `warnings without exception`() {
// language=kotlin
val result = run(
"""
fun main() {
println("")
var someVar = 1
}
""".trimIndent(), "")

assertContains(result.compilerDiagnostics.map { it.message }, "Variable is unused.")
}
}
15 changes: 10 additions & 5 deletions src/test/kotlin/com/compiler/server/ResourceE2ECompileTest.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package com.compiler.server

import com.compiler.server.generator.generateSingleProject
import com.compiler.server.model.ExecutionResult
import com.compiler.server.model.ProjectType
import com.compiler.server.model.*
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import org.junit.jupiter.api.Disabled
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.test.context.SpringBootTest
Expand Down Expand Up @@ -34,15 +32,21 @@ class ResourceE2ECompileTest : BaseResourceCompileTest {
generateSingleProject(code, projectType = platform)
)

val resultClass = when (platform) {
ProjectType.JUNIT -> JunitExecutionResult::class.java
ProjectType.JAVA -> JvmExecutionResult::class.java
ProjectType.JS, ProjectType.CANVAS, ProjectType.JS_IR -> TranslationJSResult::class.java
ProjectType.WASM, ProjectType.COMPOSE_WASM -> TranslationWasmResult::class.java
}
val result = RestTemplate().postForObject(
"${getHost()}$url", HttpEntity(body, headers), ExecutionResult::class.java
"${getHost()}$url", HttpEntity(body, headers), resultClass
)

return result ?:
throw IllegalStateException("Result is null")
}

@Test @Disabled
@Test
fun `http requests from resource folder`() {
checkResourceExamples(listOf(testDirJVM, testDirJS)) { result, file ->
val json = jacksonObjectMapper().writeValueAsString(result)
Expand Down Expand Up @@ -89,5 +93,6 @@ private fun File.isInconsistentOutput(): Boolean {
".inWholeNanoseconds",
" measureTime {",
" measureTimedValue {",
"LocalDate.now()",
).any { code.contains(it) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ fun getStringLength(obj: Any): Int? {
}
//sampleEnd

data object Some

fun main() {
fun printLength(obj: Any) {
println("Getting the length of '$obj'. Result: ${getStringLength(obj) ?: "Error: The object is not a string"} ")
}
printLength("Incomprehensibilities")
printLength(1000)
printLength(listOf(Any()))
printLength(listOf(Some))
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ fun getStringLength(obj: Any): Int? {
}
//sampleEnd

data object Some

fun main() {
fun printLength(obj: Any) {
println("Getting the length of '$obj'. Result: ${getStringLength(obj) ?: "Error: The object is not a string"} ")
}
printLength("Incomprehensibilities")
printLength(1000)
printLength(listOf(Any()))
printLength(listOf(Some))
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class Request(
data class Request(
val url: String,
val responseCode: Int
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
fun main(args: Array<String>) {
//sampleStart
val array = arrayOf("a", "b", "c")
println(array.toString()) // JVM implementation: type-and-hash gibberish
println(array.toString().substringBefore('@')) // JVM implementation: type-and-hash gibberish
println(array.contentToString()) // nicely formatted as list
//sampleEnd
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"errors":{"File.kt":[{"interval":{"start":{"line":2,"ch":4},"end":{"line":2,"ch":6}},"message":"Unresolved reference: js","severity":"ERROR","className":"ERROR"}]},"exception":null,"text":""}
{"jsCode":"//region block: polyfills\n(function () {\n if (typeof globalThis === 'object')\n return;\n Object.defineProperty(Object.prototype, '__magic__', {get: function () {\n return this;\n }, configurable: true});\n __magic__.globalThis = __magic__;\n delete Object.prototype.__magic__;\n}());\n//endregion\n(function (root, factory) {\n if (typeof define === 'function' && define.amd)\n define(['exports'], factory);\n else if (typeof exports === 'object')\n factory(module.exports);\n else\n root.moduleId = factory(typeof moduleId === 'undefined' ? {} : moduleId);\n}(globalThis, function (_) {\n 'use strict';\n //region block: pre-declaration\n initMetadataForObject(Unit, 'Unit');\n //endregion\n function Unit() {\n }\n var Unit_instance;\n function Unit_getInstance() {\n return Unit_instance;\n }\n function implement(interfaces) {\n var maxSize = 1;\n var masks = [];\n var inductionVariable = 0;\n var last = interfaces.length;\n while (inductionVariable < last) {\n var i = interfaces[inductionVariable];\n inductionVariable = inductionVariable + 1 | 0;\n var currentSize = maxSize;\n var tmp1_elvis_lhs = i.prototype.$imask$;\n var imask = tmp1_elvis_lhs == null ? i.$imask$ : tmp1_elvis_lhs;\n if (!(imask == null)) {\n masks.push(imask);\n currentSize = imask.length;\n }\n var iid = i.$metadata$.iid;\n var tmp;\n if (iid == null) {\n tmp = null;\n } else {\n // Inline function 'kotlin.let' call\n // Inline function 'kotlin.contracts.contract' call\n // Inline function 'kotlin.js.implement.<anonymous>' call\n tmp = bitMaskWith(iid);\n }\n var iidImask = tmp;\n if (!(iidImask == null)) {\n masks.push(iidImask);\n currentSize = Math.max(currentSize, iidImask.length);\n }\n if (currentSize > maxSize) {\n maxSize = currentSize;\n }\n }\n return compositeBitMask(maxSize, masks);\n }\n function bitMaskWith(activeBit) {\n var numberIndex = activeBit >> 5;\n var intArray = new Int32Array(numberIndex + 1 | 0);\n var positionInNumber = activeBit & 31;\n var numberWithSettledBit = 1 << positionInNumber;\n intArray[numberIndex] = intArray[numberIndex] | numberWithSettledBit;\n return intArray;\n }\n function compositeBitMask(capacity, masks) {\n var tmp = 0;\n var tmp_0 = new Int32Array(capacity);\n while (tmp < capacity) {\n var tmp_1 = tmp;\n var result = 0;\n var inductionVariable = 0;\n var last = masks.length;\n while (inductionVariable < last) {\n var mask = masks[inductionVariable];\n inductionVariable = inductionVariable + 1 | 0;\n if (tmp_1 < mask.length) {\n result = result | mask[tmp_1];\n }\n }\n tmp_0[tmp_1] = result;\n tmp = tmp + 1 | 0;\n }\n return tmp_0;\n }\n function objectCreate(proto) {\n proto = proto === VOID ? null : proto;\n return Object.create(proto);\n }\n function defineProp(obj, name, getter, setter) {\n return Object.defineProperty(obj, name, {configurable: true, get: getter, set: setter});\n }\n function equals(obj1, obj2) {\n if (obj1 == null) {\n return obj2 == null;\n }\n if (obj2 == null) {\n return false;\n }\n if (typeof obj1 === 'object' && typeof obj1.equals === 'function') {\n return obj1.equals(obj2);\n }\n if (obj1 !== obj1) {\n return obj2 !== obj2;\n }\n if (typeof obj1 === 'number' && typeof obj2 === 'number') {\n var tmp;\n if (obj1 === obj2) {\n var tmp_0;\n if (obj1 !== 0) {\n tmp_0 = true;\n } else {\n // Inline function 'kotlin.js.asDynamic' call\n var tmp_1 = 1 / obj1;\n // Inline function 'kotlin.js.asDynamic' call\n tmp_0 = tmp_1 === 1 / obj2;\n }\n tmp = tmp_0;\n } else {\n tmp = false;\n }\n return tmp;\n }\n return obj1 === obj2;\n }\n function protoOf(constructor) {\n return constructor.prototype;\n }\n function createMetadata(kind, name, defaultConstructor, associatedObjectKey, associatedObjects, suspendArity) {\n var undef = VOID;\n var iid = kind === 'interface' ? generateInterfaceId() : VOID;\n return {kind: kind, simpleName: name, associatedObjectKey: associatedObjectKey, associatedObjects: associatedObjects, suspendArity: suspendArity, $kClass$: undef, defaultConstructor: defaultConstructor, iid: iid};\n }\n function generateInterfaceId() {\n if (globalInterfaceId === VOID) {\n globalInterfaceId = 0;\n }\n // Inline function 'kotlin.js.unsafeCast' call\n globalInterfaceId = globalInterfaceId + 1 | 0;\n // Inline function 'kotlin.js.unsafeCast' call\n return globalInterfaceId;\n }\n var globalInterfaceId;\n function initMetadataFor(kind, ctor, name, defaultConstructor, parent, interfaces, suspendArity, associatedObjectKey, associatedObjects) {\n if (!(parent == null)) {\n ctor.prototype = Object.create(parent.prototype);\n ctor.prototype.constructor = ctor;\n }\n var metadata = createMetadata(kind, name, defaultConstructor, associatedObjectKey, associatedObjects, suspendArity);\n ctor.$metadata$ = metadata;\n if (!(interfaces == null)) {\n var receiver = !equals(metadata.iid, VOID) ? ctor : ctor.prototype;\n receiver.$imask$ = implement(interfaces);\n }\n }\n function initMetadataForObject(ctor, name, defaultConstructor, parent, interfaces, suspendArity, associatedObjectKey, associatedObjects) {\n var kind = 'object';\n initMetadataFor(kind, ctor, name, defaultConstructor, parent, interfaces, suspendArity, associatedObjectKey, associatedObjects);\n }\n function initMetadataForCompanion(ctor, parent, interfaces, suspendArity) {\n initMetadataForObject(ctor, 'Companion', VOID, parent, interfaces, suspendArity, VOID, VOID);\n }\n function get_VOID() {\n _init_properties_void_kt__3zg9as();\n return VOID;\n }\n var VOID;\n var properties_initialized_void_kt_e4ret2;\n function _init_properties_void_kt__3zg9as() {\n if (!properties_initialized_void_kt_e4ret2) {\n properties_initialized_void_kt_e4ret2 = true;\n VOID = void 0;\n }\n }\n function main() {\n alert('alert from Kotlin!');\n }\n function mainWrapper() {\n main();\n }\n //region block: init\n Unit_instance = new Unit();\n //endregion\nif (typeof get_output !== \"undefined\") {\n get_output();\n output = new BufferedOutput();\n _.output = get_output();\n}\n mainWrapper();\n return _;\n}));\nmoduleId.output?.buffer_1;\n\n","exception":null,"errors":{"File.kt":[]},"text":""}
Loading