Yurin
12/31/2025, 3:59 PMpackage yurin.mal
import Avalonia.Controls.Button
import Avalonia.Controls.StackPanel
import Avalonia.Controls.TextBlock
import Avalonia.Markup.Declarative.Children
import Avalonia.Markup.Declarative.ComponentBase
import Avalonia.Markup.Declarative.OnClick
import Avalonia.Markup.Declarative.Text
class MALComponent : ComponentBase() {
private var count = 0
override fun Build(): Any {
val stackPanel = StackPanel()
stackPanel.Children()
val textBlock = TextBlock()
textBlock.Text("Avalonia with kotlin demo")
stackPanel.Children!!.Add(textBlock)
val button = Button()
button.OnClick { _ ->
count++
StateHasChanged()
}
stackPanel.Children!!.Add(button)
return stackPanel
}
}
The first issue is that calling stackPanel.Children() results in a receiver type mismatch error when resolving the Children function.
The second issue is the same kind of problem with textBlock.Text("Avalonia with kotlin demo").
The third issue is that calling button.OnClick { _ -> count++; StateHasChanged() } also fails due to function resolution.
The fourth issue is a consequence of the third one.
I’ve already implemented a stub generator that parses CLR assemblies into Kotlin source code for IDEA to use for syntax analysis and code completion. Under IDEA, when using these stubs, the functions are resolved correctly and this code shows no errors.
For the first issue, IDEA successfully resolves the top-level Children function:
public fun <reified TPanel : Avalonia.Controls.Panel?> TPanel?.Children(vararg children: Avalonia.Controls.Control?): TPanel? = kotlin.TODO()
For the second issue, IDEA successfully resolves the top-level Text function:
public fun <reified T : Avalonia.Controls.TextBlock?> T?.Text(
value: kotlin.String?,
bindingMode: System.Nullable1<Avalonia.Data.BindingMode?>? = kotlin.TODO(),
converter: Avalonia.Data.Converters.IValueConverter? = kotlin.TODO(),
bindingSource: kotlin.Any? = kotlin.TODO(),
ps: kotlin.String? = kotlin.TODO()
): T? = kotlin.TODO()
For the third issue, IDEA successfully resolves the top-level OnClick function:
public fun <reified T : Avalonia.Controls.Button?> T?.OnClick(
action: System.Action1<Avalonia.Interactivity.RoutedEventArgs?>?
): T? = kotlin.TODO()
But in the actual compiler, it instead resolves to the member function of `Button`:
... class Button ... {
protected open fun OnClick(): kotlin.Unit? = kotlin.TODO()
}
I tried debugging the corresponding FirFunction objects and their properties all look normal. I also checked the inheritance hierarchy of the related FirRegularClass objects and confirmed there’s no issue there. I also tried removing reified and nullability from these functions, but the result is still the same.
Here is the generated raw FIR:
FILE: MALComponent.kt
public final? class MALComponent : ComponentBase {
public? constructor(): R|yurin/mal/MALComponent| {
super<ComponentBase>()
}
private final? var count: <implicit> = IntegerLiteral(0)
private get(): <implicit>
private set(value: <implicit>): R|kotlin/Unit|
public? open? override fun Build(): Any {
lval stackPanel: <implicit> = StackPanel#()
stackPanel#.Children#()
lval textBlock: <implicit> = TextBlock#()
textBlock#.Text#(String(Avalonia with kotlin demo))
stackPanel#.Children#!!.Add#(textBlock#)
lval button: <implicit> = Button#()
button#.OnClick#(<L> = OnClick@fun <implicit>.<anonymous>(<unused var>: <implicit>): <implicit> <inline=Unknown> {
count#++
StateHasChanged#()
}
)
stackPanel#.Children#!!.Add#(button#)
^Build stackPanel#
}
}
And the FIR after processing:
FILE: MALComponent.kt
public final class MALComponent : R|Avalonia/Markup/Declarative/ComponentBase| {
public constructor(): R|yurin/mal/MALComponent| {
super<R|Avalonia/Markup/Declarative/ComponentBase|>()
}
private final var count: R|kotlin/Int| = Int(0)
private get(): R|kotlin/Int|
private set(value: R|kotlin/Int|): R|kotlin/Unit|
protected open override fun Build(): R|kotlin/Any| {
lval stackPanel: R|Avalonia/Controls/StackPanel| = R|Avalonia/Controls/StackPanel|()
R|<local>/stackPanel|.<Ambiguity: Children, [Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children, Avalonia/Markup/Declarative/Children]>#()
lval textBlock: R|Avalonia/Controls/TextBlock| = R|Avalonia/Controls/TextBlock|()
R|<local>/textBlock|.<Ambiguity: Text, [Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text, Avalonia/Markup/Declarative/Text]>#(String(Avalonia with kotlin demo))
R|<local>/stackPanel|.R|Avalonia/Controls/Panel.Children|!!.R|System/Collections/IList.Add|(R|<local>/textBlock|)
lval button: R|Avalonia/Controls/Button| = R|Avalonia/Controls/Button|()
R|<local>/button|.R|Avalonia/Controls/Button.OnClick<Inapplicable(INAPPLICABLE_ARGUMENTS_MAPPING_ERROR): Avalonia/Controls/Button.OnClick>#|(<L> = OnClick@fun <anonymous>(<unused var>: <ERROR TYPE REF: Cannot infer type for parameter <unused var>>): <ERROR TYPE REF: Cannot infer type variable TypeVariable(_L)> <inline=Unknown> {
{
lval <unary>: R|kotlin/Int| = this@R|yurin/mal/MALComponent|.R|yurin/mal/MALComponent.count|
this@R|yurin/mal/MALComponent|.R|yurin/mal/MALComponent.count| = R|<local>/<unary>|.R|kotlin/Int.inc|()
R|<local>/<unary>|
}
^ this@R|yurin/mal/MALComponent|.R|Avalonia/Markup/Declarative/ComponentBase.StateHasChanged|()
}
)
R|<local>/stackPanel|.R|Avalonia/Controls/Panel.Children|!!.R|System/Collections/IList.Add|(R|<local>/button|)
^Build R|<local>/stackPanel|
}
}Youssef Shoaib [MOD]
12/31/2025, 5:13 PMYurin
01/02/2026, 3:06 AMdotnet SDK.
Modify -dotnet-version in ./script/AvaloniaClrCompilation.ps1 (you can check your installed versions under C:\Program Files\dotnet\shared\<http://Microsoft.NETCore.App|Microsoft.NETCore.App>\).
1. Run the script ./script/AvaloniaClrCompilation.ps1.
2. Modify -dotnet-version in ./script/AvaloniaClrCompilation.ps1 (you can check your installed versions under C:\Program Files\dotnet\shared\<http://Microsoft.NETCore.App|Microsoft.NETCore.App>\).
3. Run the script ./script/AvaloniaClrCompilation.ps1.