Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Kotlin] Uses Kotlin's coroutines to handle the asynchronous operation and returns the result directly #30082

Merged
merged 2 commits into from
Oct 30, 2023
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{%- set struct = encodable.get_underlying_struct() -%}
ChipStructs.{{source.name}}Cluster{{struct.name}}
{%- else -%}
{{encodable.boxed_java_type}}
{{encodable.kotlin_type}}
{%- endif -%}
{%- endmacro -%}

Expand All @@ -24,7 +24,7 @@
{%- set struct = encodable.get_underlying_struct() -%}
ChipStructs.{{source.name}}Cluster{{struct.name}}
{%- else -%}
{{encodable.boxed_java_type}}
{{encodable.kotlin_type}}
{%- endif -%}
{%- endmacro -%}

Expand All @@ -35,7 +35,7 @@
{%- set struct = encodable.get_underlying_struct() -%}
ChipStructs.{{source.name}}Cluster{{struct.name}}
{%- else -%}
{{encodable.boxed_java_type}}
{{encodable.kotlin_type}}
{%- endif -%}
{%- endmacro -%}

Expand All @@ -61,77 +61,84 @@ package matter.devicecontroller.cluster.clusters
import java.util.ArrayList
{% set typeLookup = idl | createLookupContext(cluster) %}
class {{cluster.name}}Cluster(private val endpointId: UShort) {
companion object {
const val CLUSTER_ID: UInt = {{cluster.code}}u
}
{% for command in cluster.commands | sort(attribute='code') -%}
{%- set callbackName = command | javaCommandCallbackName() -%}
{%- if not command.is_timed_invoke %}
fun {{command.name | lowfirst_except_acronym}}(callback: {{callbackName}}Callback
{%- if command.input_param -%}
{%- for field in (cluster.structs | named(command.input_param)).fields -%}
, {{field.name | lowfirst_except_acronym}}: {{encode_value(cluster, field | asEncodable(typeLookup), 0)}}
{%- endfor -%}
{%- endif -%}
) {
// Implementation needs to be added here
}
{%- endif %}

fun {{command.name | lowfirst_except_acronym}}(callback: {{callbackName}}Callback
{%- if command.input_param -%}
{%- for field in (cluster.structs | named(command.input_param)).fields -%}
, {{field.name | lowfirst_except_acronym}}: {{encode_value(cluster, field | asEncodable(typeLookup), 0)}}
{%- endfor -%}
{%- endif -%}
, timedInvokeTimeoutMs: Int) {
// Implementation needs to be added here
}
{% endfor %}
{%- set already_handled_command = [] -%}
{%- for command in cluster.commands | sort(attribute='code') -%}
{%- if command | isCommandNotDefaultCallback() -%}
{%- set callbackName = command | javaCommandCallbackName() -%}
{%- if callbackName not in already_handled_command %}
interface {{callbackName}}Callback {
fun onSuccess(
{%- for field in (cluster.structs | named(command.output_param)).fields -%}
{{field.name | lowfirst_except_acronym}}: {{encode_value(cluster, field | asEncodable(typeLookup), 0)}}{% if not loop.last %}, {% endif %}
{%- endfor -%}
)
fun onError(error: Exception)
}
class {{callbackName}}(
{%- for field in (cluster.structs | named(command.output_param)).fields %}
val {{field.name | lowfirst_except_acronym}}: {{encode_value(cluster, field | asEncodable(typeLookup), 0)}}
{%- if not loop.last %}, {% endif %}
{%- endfor %}
)
{% if already_handled_command.append(callbackName) -%}
{%- endif -%}
{%- endif -%}
{%- endif -%}
{%- endfor %}

{%- set already_handled_attribute = [] -%}
{% for attribute in cluster.attributes | rejectattr('definition', 'is_field_global_name', typeLookup) %}
{%- set encodable = attribute.definition | asEncodable(typeLookup) -%}
{%- set interfaceName = attribute | javaAttributeCallbackName(typeLookup) -%}
{%- if interfaceName not in already_handled_attribute %}
interface {{interfaceName}} {
fun onSuccess(value: {{encode_value(cluster, encodable, 0)}})
fun onError(ex: Exception)
fun onSubscriptionEstablished(subscriptionId: Long)
}
class {{interfaceName}}(
val value: {{encode_value(cluster, encodable, 0)}}
)
{% if already_handled_attribute.append(interfaceName) -%}
{#- This block does nothing, it only exists to append to already_handled_attribute. -#}
{%- endif -%}
{%- endif -%}
{% endfor -%}

{%- for command in cluster.commands | sort(attribute='code') -%}
{%- set callbackName = command | javaCommandCallbackName() -%}
{%- if not command.is_timed_invoke %}
suspend fun {{command.name | lowfirst_except_acronym}}(
{%- if command.input_param -%}
{%- for field in (cluster.structs | named(command.input_param)).fields -%}
{{field.name | lowfirst_except_acronym}}: {{encode_value(cluster, field | asEncodable(typeLookup), 0)}}
{%- if not loop.last -%}, {% endif %}
{%- endfor -%}
{%- endif -%}
)
{%- if command | hasResponse -%}
: {{callbackName}} {
{%- else %} {
{%- endif %}
// Implementation needs to be added here
}
{%- endif %}

suspend fun {{command.name | lowfirst_except_acronym}}(
{%- if command.input_param -%}
{%- for field in (cluster.structs | named(command.input_param)).fields -%}
{{field.name | lowfirst_except_acronym}}: {{encode_value(cluster, field | asEncodable(typeLookup), 0)}}
{%- if not loop.last -%}, {% endif %}
{%- endfor -%}
, timedInvokeTimeoutMs: Int)
{%- else -%}
timedInvokeTimeoutMs: Int)
{%- endif -%}
{%- if command | hasResponse -%}
: {{callbackName}} {
{%- else %} {
{%- endif %}
// Implementation needs to be added here
}
{% endfor -%}

{% for attribute in cluster.attributes | sort(attribute='code') %}
fun read{{ attribute.definition.name | upfirst }}Attribute(
callback: {{ attribute | javaAttributeCallbackName(typeLookup) }}
) {
{%- set interfaceName = attribute | javaAttributeCallbackName(typeLookup) %}
suspend fun read{{ attribute.definition.name | upfirst }}Attribute(): {{interfaceName}} {
// Implementation needs to be added here
}
{% if attribute | isFabricScopedList(typeLookup) %}
fun read{{ attribute.definition.name | upfirst }}AttributeWithFabricFilter(
callback: {{ attribute | javaAttributeCallbackName(typeLookup) }},
suspend fun read{{ attribute.definition.name | upfirst }}AttributeWithFabricFilter(
isFabricFiltered: Boolean
) {
): {{interfaceName}} {
// Implementation needs to be added here
}

Expand All @@ -140,29 +147,29 @@ class {{cluster.name}}Cluster(private val endpointId: UShort) {
{%- set encodable = attribute.definition | asEncodable(typeLookup) -%}
{%- set encodable2 = attribute.definition | asEncodable(typeLookup) -%}
{%- if not attribute.requires_timed_write %}
fun write{{ attribute.definition.name | upfirst }}Attribute(
callback: DefaultClusterCallback,
suspend fun write{{ attribute.definition.name | upfirst }}Attribute(
value: {{ encode_value_without_optional_nullable(cluster, encodable, 0) }}
) {
// Implementation needs to be added here
}
{% endif %}
fun write{{ attribute.definition.name | upfirst }}Attribute(
callback: DefaultClusterCallback,
suspend fun write{{ attribute.definition.name | upfirst }}Attribute(
value: {{ encode_value_without_optional_nullable(cluster, encodable2, 0) }},
timedWriteTimeoutMs: Int
) {
// Implementation needs to be added here
}
{% endif %}
{%- if attribute.is_subscribable %}
fun subscribe{{ attribute.definition.name | upfirst }}Attribute(
callback: {{ attribute | javaAttributeCallbackName(typeLookup) }},
suspend fun subscribe{{ attribute.definition.name | upfirst }}Attribute(
minInterval: Int,
maxInterval: Int
) {
): {{interfaceName}} {
// Implementation needs to be added here
}
{% endif -%}
{%- endfor -%}
{%- endfor %}
companion object {
const val CLUSTER_ID: UInt = {{cluster.code}}u
}
}
68 changes: 21 additions & 47 deletions scripts/py_matter_idl/matter_idl/generators/kotlin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,9 +212,9 @@ def JavaAttributeCallbackName(attr: Attribute, context: TypeLookupContext) -> st
global_name = FieldToGlobalName(attr.definition, context)

if global_name:
return '{}AttributeCallback'.format(GlobalNameToJavaName(global_name))
return '{}'.format(GlobalNameToJavaName(global_name))

return '{}AttributeCallback'.format(capitalcase(attr.definition.name))
return '{}Attribute'.format(capitalcase(attr.definition.name))


def IsFieldGlobalName(field: Field, context: TypeLookupContext) -> bool:
Expand Down Expand Up @@ -404,43 +404,6 @@ def get_underlying_enum(self):
raise Exception("Enum %s not found" % self.data_type.name)
return e

@property
def boxed_java_type(self):
t = ParseDataType(self.data_type, self.context)

if isinstance(t, FundamentalType):
if t == FundamentalType.BOOL:
return "Boolean"
elif t == FundamentalType.FLOAT:
return "Float"
elif t == FundamentalType.DOUBLE:
return "Double"
else:
raise Exception("Unknown fundamental type")
elif isinstance(t, BasicInteger):
# the >= 3 will include int24_t to be considered "long"
if t.byte_count >= 3:
return "Long"
else:
return "Integer"
elif isinstance(t, BasicString):
if t.is_binary:
return "ByteArray"
else:
return "String"
elif isinstance(t, IdlEnumType):
if t.base_type.byte_count >= 3:
return "Long"
else:
return "Integer"
elif isinstance(t, IdlBitmapType):
if t.base_type.byte_count >= 3:
return "Long"
else:
return "Integer"
else:
return "Object"

@property
def kotlin_type(self):
t = ParseDataType(self.data_type, self.context)
Expand All @@ -455,17 +418,22 @@ def kotlin_type(self):
else:
raise Exception("Unknown fundamental type")
elif isinstance(t, BasicInteger):
# the >= 3 will include int24_t to be considered "long"
if t.is_signed:
if t.byte_count >= 3:
return "Long"
else:
if t.byte_count <= 1:
return "Byte"
if t.byte_count <= 2:
return "Short"
if t.byte_count <= 4:
return "Int"
else:
if t.byte_count >= 3:
return "ULong"
else:
return "Long"
else: # unsigned
if t.byte_count <= 1:
return "UByte"
if t.byte_count <= 2:
return "UShort"
if t.byte_count <= 4:
return "UInt"
return "ULong"
elif isinstance(t, BasicString):
if t.is_binary:
return "ByteArray"
Expand Down Expand Up @@ -615,6 +583,11 @@ def IsFabricScopedList(attr: Attribute, lookup: TypeLookupContext) -> bool:
return struct and struct.qualities == StructQuality.FABRIC_SCOPED


def CommandHasResponse(command: Command) -> bool:
"""Returns true if a command has a specific response."""
return command.output_param != "DefaultSuccess"


def IsResponseStruct(s: Struct) -> bool:
return s.tag == StructTag.RESPONSE

Expand Down Expand Up @@ -649,6 +622,7 @@ def __init__(self, storage: GeneratorStorage, idl: Idl, **kargs):
self.jinja_env.filters['createLookupContext'] = CreateLookupContext
self.jinja_env.filters['canGenerateSubscribe'] = CanGenerateSubscribe
self.jinja_env.filters['isFabricScopedList'] = IsFabricScopedList
self.jinja_env.filters['hasResponse'] = CommandHasResponse

self.jinja_env.tests['is_response_struct'] = IsResponseStruct
self.jinja_env.tests['is_using_global_callback'] = _IsUsingGlobalCallback
Expand Down
Loading
Loading