Skip to content

Commit

Permalink
[Kotlin] Uses Kotlin's coroutines to handle the asynchronous operatio…
Browse files Browse the repository at this point in the history
…n and returns the result directly (#30082)

* Update the kotlin type mapping

* Remove callback from fun
  • Loading branch information
yufengwangca authored and pull[bot] committed Nov 30, 2023
1 parent baf4966 commit 1126340
Show file tree
Hide file tree
Showing 100 changed files with 7,129 additions and 17,152 deletions.
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

0 comments on commit 1126340

Please sign in to comment.