Skip to content

Commit d0d5a1d

Browse files
Sync with master, do some refactor
1 parent b85ac51 commit d0d5a1d

File tree

14 files changed

+681
-1062
lines changed

14 files changed

+681
-1062
lines changed

Diff for: build.gradle.kts

+1-3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ plugins {
1212

1313
val deploy: Configuration by configurations.creating
1414

15-
val serializationFlagProperty = "jupyter.serialization.enabled"
16-
1715
deploy.apply {
1816
exclude("org.jetbrains.kotlinx", "kotlinx-serialization-json-jvm")
1917
exclude("org.jetbrains.kotlinx", "kotlinx-serialization-core-jvm")
@@ -117,7 +115,7 @@ tasks {
117115
"junit.jupiter.execution.parallel.enabled" to doParallelTesting.toString() as Any,
118116
"junit.jupiter.execution.parallel.mode.default" to "concurrent",
119117
"junit.jupiter.execution.parallel.mode.classes.default" to "concurrent",
120-
serializationFlagProperty to "true"
118+
"jupyter.serialization.enabled" to "true"
121119
)
122120
}
123121

Diff for: jupyter-lib/api/src/main/kotlin/org/jetbrains/kotlinx/jupyter/api/VariableState.kt

+32-57
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package org.jetbrains.kotlinx.jupyter.api
22

33
import java.lang.reflect.Field
44
import kotlin.reflect.KProperty
5-
import kotlin.reflect.KProperty1
65
import kotlin.reflect.jvm.isAccessible
76

87
interface VariableState {
@@ -34,16 +33,17 @@ data class VariableStateImpl(
3433
try {
3534
value.toString()
3635
} catch (e: Throwable) {
36+
if (e is StackOverflowError) {
37+
isRecursive = true
38+
}
3739
"${value::class.simpleName}: [exception thrown: $e]"
3840
}
3941
}
4042
}
4143
override var isRecursive: Boolean = false
42-
private var isLargeForString: Boolean = false
4344

44-
private val valCache = VariableStateCache<Result<Any?>> (
45-
{
46-
oldValue, newValue ->
45+
private val valCache = VariableStateCache<Result<Any?>>(
46+
{ oldValue, newValue ->
4747
oldValue.getOrNull() !== newValue.getOrNull()
4848
},
4949
{
@@ -63,75 +63,50 @@ data class VariableStateImpl(
6363
}
6464
}
6565

66-
override val stringValue: String? get() = stringCache.get()
66+
override val stringValue: String? get() = stringCache.getOrNull()
6767

6868
override val value: Result<Any?> get() = valCache.get()
6969

7070
companion object {
71-
private fun <T : KProperty<*>, R> T.asAccessible(action: (T) -> R): R {
71+
@SuppressWarnings("DEPRECATED")
72+
private fun <R> Field.asAccessible(action: (Field) -> R): R {
7273
val wasAccessible = isAccessible
7374
isAccessible = true
7475
val res = action(this)
7576
isAccessible = wasAccessible
7677
return res
7778
}
7879
}
79-
private val customDelegate = DependentLazyDelegate {
80-
fun getRecursiveObjectName(): String {
81-
val kClassName = cachedValue.getOrNull()!!::class.simpleName
82-
return "$kClassName: recursive structure"
83-
}
84-
if (cachedValue.getOrNull() == null) {
85-
return@DependentLazyDelegate null
86-
}
87-
handleIfRecursiveStructure()
88-
try {
89-
cachedValue.getOrNull().toString()
90-
isRecursive = false
91-
isLargeForString = false
92-
} catch (e: VirtualMachineError) {
93-
when (e) {
94-
is StackOverflowError -> {
95-
isRecursive = true
96-
}
97-
is OutOfMemoryError -> {
98-
isLargeForString = true
99-
}
100-
else -> {
101-
return@DependentLazyDelegate null
102-
}
103-
}
104-
}
105-
}
10680

107-
private class VariableStateCache<T>(
108-
val equalityChecker: (T, T) -> Boolean = { x, y -> x == y },
109-
val calculate: (T?) -> T
110-
) {
111-
private var cachedVal: T? = null
112-
private var shouldRenew: Boolean = true
81+
private class VariableStateCache<T>(
82+
val equalityChecker: (T, T) -> Boolean = { x, y -> x == y },
83+
val calculate: (T?) -> T
84+
) {
85+
private var cachedVal: T? = null
86+
private var shouldRenew: Boolean = true
11387

114-
fun getOrNull(): T? {
115-
return if (shouldRenew) {
116-
calculate(cachedVal).also {
117-
cachedVal = it
118-
shouldRenew = false
88+
fun getOrNull(): T? {
89+
return if (shouldRenew) {
90+
calculate(cachedVal).also {
91+
cachedVal = it
92+
shouldRenew = false
93+
}
94+
} else {
95+
cachedVal
11996
}
120-
} else {
121-
cachedVal
12297
}
123-
}
12498

125-
fun get(): T = getOrNull()!!
99+
fun get(): T = getOrNull()!!
126100

127-
fun update() {
128-
shouldRenew = true
129-
}
101+
fun update() {
102+
shouldRenew = true
103+
}
130104

131-
fun forceUpdate(): Boolean {
132-
val oldVal = getOrNull()
133-
update()
134-
val newVal = get()
135-
return oldVal != null && equalityChecker(oldVal, newVal)
105+
fun forceUpdate(): Boolean {
106+
val oldVal = getOrNull()
107+
update()
108+
val newVal = get()
109+
return oldVal != null && equalityChecker(oldVal, newVal)
110+
}
136111
}
137112
}

Diff for: src/main/kotlin/org/jetbrains/kotlinx/jupyter/apiImpl.kt

+1-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import org.jetbrains.kotlinx.jupyter.api.RenderersProcessor
1212
import org.jetbrains.kotlinx.jupyter.api.ResultsAccessor
1313
import org.jetbrains.kotlinx.jupyter.api.VariableState
1414
import org.jetbrains.kotlinx.jupyter.api.libraries.LibraryResolutionRequest
15+
import org.jetbrains.kotlinx.jupyter.repl.InternalEvaluator
1516
import org.jetbrains.kotlinx.jupyter.repl.impl.SharedReplContext
1617

1718
class DisplayResultWrapper private constructor(
@@ -152,16 +153,10 @@ class NotebookImpl(
152153
get() = JavaRuntime
153154

154155
fun updateVariablesState(evaluator: InternalEvaluator) {
155-
variablesState += evaluator.variablesHolder
156-
currentCellVariables = evaluator.cellVariables
157156
_unchangedVariables.clear()
158157
_unchangedVariables.addAll(evaluator.getUnchangedVariables())
159158
}
160159

161-
fun updateVariablesState(varsStateUpdate: Map<String, VariableState>) {
162-
variablesState += varsStateUpdate
163-
}
164-
165160
fun variablesReportAsHTML(): String {
166161
return generateHTMLVarsReport(variablesState)
167162
}

Diff for: src/main/kotlin/org/jetbrains/kotlinx/jupyter/message_types.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,9 @@ enum class MessageType(val contentClass: KClass<out MessageContent>) {
9090
LIST_ERRORS_REQUEST(ListErrorsRequest::class),
9191
LIST_ERRORS_REPLY(ListErrorsReply::class),
9292

93-
SERIALIZATION_REQUEST(SerializationRequest::class),
94-
SERIALIZATION_REPLY(SerializationReply::class);
93+
// from Serialization_Request
94+
VARIABLES_VIEW_REQUEST(SerializationRequest::class),
95+
VARIABLES_VIEW_REPLY(SerializationReply::class);
9596

9697
val type: String
9798
get() = name.lowercase()

Diff for: src/main/kotlin/org/jetbrains/kotlinx/jupyter/protocol.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -315,8 +315,8 @@ fun JupyterConnection.Socket.shellMessagesHandler(msg: Message, repl: ReplForJup
315315
return
316316
}
317317
log.debug("Message type in CommOpen: $msg, ${msg.type}")
318-
val data = content.data ?: return sendWrapped(msg, makeReplyMessage(msg, MessageType.SERIALIZATION_REPLY))
319-
if (data.isEmpty()) return sendWrapped(msg, makeReplyMessage(msg, MessageType.SERIALIZATION_REPLY))
318+
val data = content.data ?: return sendWrapped(msg, makeReplyMessage(msg, MessageType.VARIABLES_VIEW_REPLY))
319+
if (data.isEmpty()) return sendWrapped(msg, makeReplyMessage(msg, MessageType.VARIABLES_VIEW_REPLY))
320320
log.debug("Message data: $data")
321321
val messageContent = getVariablesDescriptorsFromJson(data)
322322
connection.launchJob {
@@ -348,10 +348,10 @@ fun JupyterConnection.Socket.shellMessagesHandler(msg: Message, repl: ReplForJup
348348
connection.launchJob {
349349
if (content.topLevelDescriptorName.isNotEmpty()) {
350350
repl.serializeVariables(content.topLevelDescriptorName, content.descriptorsState, commID = content.commId, content.pathToDescriptor) { result ->
351-
sendWrapped(msg, makeReplyMessage(msg, MessageType.SERIALIZATION_REPLY, content = result))
351+
sendWrapped(msg, makeReplyMessage(msg, MessageType.VARIABLES_VIEW_REPLY, content = result))
352352
}
353353
} else {
354-
sendWrapped(msg, makeReplyMessage(msg, MessageType.SERIALIZATION_REPLY, content = null))
354+
sendWrapped(msg, makeReplyMessage(msg, MessageType.VARIABLES_VIEW_REPLY, content = null))
355355
}
356356
}
357357
}

Diff for: src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl.kt

+3-4
Original file line numberDiff line numberDiff line change
@@ -458,9 +458,8 @@ class ReplForJupyterImpl(
458458
} ?: emptyList()
459459

460460
notebook.updateVariablesState(internalEvaluator)
461-
// printVars()
462461
// printUsagesInfo(jupyterId, cellVariables[jupyterId - 1])
463-
val variablesCells: Map<String, Int> = notebook.variablesState.mapValues { internalEvaluator.findVariableCell(it.key) }
462+
val variablesCells: Map<String, Int?> = notebook.variablesState.mapValues { internalEvaluator.findVariableCell(it.key) }
464463
val serializedData = variablesSerializer.serializeVariables(jupyterId - 1, notebook.variablesState, oldDeclarations, variablesCells, notebook.unchangedVariables)
465464

466465
GlobalScope.launch(Dispatchers.Default) {
@@ -576,8 +575,8 @@ class ReplForJupyterImpl(
576575
private fun doSerializeVariables(args: SerializationArgs): SerializationReply {
577576
val resultMap = mutableMapOf<String, SerializedVariablesState>()
578577
val cellId = if (args.cellId != -1) args.cellId else {
579-
val watcherInfo = internalEvaluator.findVariableCell(args.topLevelVarName) + 1
580-
val finalAns = if (watcherInfo == - 1) 1 else watcherInfo
578+
val watcherInfo = internalEvaluator.findVariableCell(args.topLevelVarName)
579+
val finalAns = if (watcherInfo == null) 1 else watcherInfo + 1
581580
finalAns
582581
}
583582
args.descriptorsState.forEach { (name, state) ->

Diff for: src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/InternalEvaluator.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ interface InternalEvaluator {
3434
/**
3535
* Get a cellId where a particular variable is declared
3636
*/
37-
fun findVariableCell(variableName: String): Int
37+
fun findVariableCell(variableName: String): Int?
3838

3939
fun getVariablesDeclarationInfo(): Map<String, Int>
4040

Diff for: src/main/kotlin/org/jetbrains/kotlinx/jupyter/repl/impl/InternalEvaluatorImpl.kt

+17-8
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@ import org.jetbrains.kotlinx.jupyter.exceptions.ReplCompilerException
1515
import org.jetbrains.kotlinx.jupyter.repl.ContextUpdater
1616
import org.jetbrains.kotlinx.jupyter.repl.InternalEvalResult
1717
import org.jetbrains.kotlinx.jupyter.repl.InternalEvaluator
18+
import org.jetbrains.kotlinx.jupyter.repl.InternalVariablesMarkersProcessor
1819
import java.lang.reflect.Field
1920
import java.lang.reflect.Modifier
20-
import org.jetbrains.kotlinx.jupyter.repl.InternalVariablesMarkersProcessor
21-
import kotlin.reflect.KMutableProperty1
2221
import kotlin.reflect.KProperty1
2322
import kotlin.reflect.full.declaredMemberProperties
2423
import kotlin.script.experimental.api.ResultValue
@@ -170,18 +169,28 @@ internal class InternalEvaluatorImpl(
170169
val kClass = target.scriptClass ?: return emptyMap()
171170
val cellClassInstance = target.scriptInstance!!
172171

173-
val fields = kClass.declaredMemberProperties
172+
val fields = kClass.java.declaredFields
173+
// ignore implementation details of top level like script instance and result value
174+
val kProperties = kClass.declaredMemberProperties.associateBy { it.name }
175+
174176
return mutableMapOf<String, VariableStateImpl>().apply {
177+
val addedDeclarations = mutableSetOf<String>()
175178
for (property in fields) {
176-
@Suppress("UNCHECKED_CAST")
177-
property as KProperty1<Any, *>
178-
if (internalVariablesMarkersProcessor.isInternal(property)) continue
179-
180179
val state = VariableStateImpl(property, cellClassInstance)
180+
181+
val isInternalKProperty = kProperties[property.name]?.let {
182+
@Suppress("UNCHECKED_CAST")
183+
it as KProperty1<Any, *>
184+
internalVariablesMarkersProcessor.isInternal(it)
185+
}
186+
187+
if (isInternalKProperty == true || !kProperties.contains(property.name)) continue
188+
181189
variablesWatcher.addDeclaration(cellId, property.name)
190+
addedDeclarations.add(property.name)
182191

183192
// it was val, now it's var
184-
if (property is KMutableProperty1) {
193+
if (isValField(property)) {
185194
variablesHolder.remove(property.name)
186195
} else {
187196
variablesHolder[property.name] = state

Diff for: src/main/kotlin/org/jetbrains/kotlinx/jupyter/serializationUtils.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ class VariablesSerializer(
363363
clearOldData(currentCellId, cellVariables)
364364
}
365365

366-
fun serializeVariables(cellId: Int, variablesState: Map<String, VariableState>, oldDeclarations: Map<String, Int>, variablesCells: Map<String, Int>, unchangedVariables: Set<String>): Map<String, SerializedVariablesState> {
366+
fun serializeVariables(cellId: Int, variablesState: Map<String, VariableState>, oldDeclarations: Map<String, Int>, variablesCells: Map<String, Int?>, unchangedVariables: Set<String>): Map<String, SerializedVariablesState> {
367367
if (!isSerializationActive) return emptyMap()
368368

369369
if (variablesState.isEmpty()) {

Diff for: src/main/kotlin/org/jetbrains/kotlinx/jupyter/util.kt

-2
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,12 @@ class VariablesUsagesPerCellWatcher<K : Any, V : Any> {
8686
private val unchangedVariables: MutableSet<V> = mutableSetOf()
8787

8888
fun removeOldDeclarations(address: K, newDeclarations: Set<V>) {
89-
// removeIf?
9089
cellVariables[address]?.forEach {
9190
val predicate = newDeclarations.contains(it) && variablesDeclarationInfo[it] != address
9291
if (predicate) {
9392
variablesDeclarationInfo.remove(it)
9493
unchangedVariables.remove(it)
9594
}
96-
// predicate
9795
}
9896

9997
// add old declarations as unchanged

0 commit comments

Comments
 (0)