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

Move ClusterWriteMapping.java to be generated from matter.idl #25773

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
091b970
Some initial changes
andy31415 Mar 20, 2023
b77d8e8
Parser support for timed writes
andy31415 Mar 20, 2023
83b359b
Small doc update
andy31415 Mar 20, 2023
7c56e30
Matter idl support for timed write
andy31415 Mar 20, 2023
8564f1c
Fix indent and codegen all
andy31415 Mar 20, 2023
dd9a5b2
Remove extra line from readme
andy31415 Mar 20, 2023
90c98d0
Merge branch 'timed_write_attribute_in_idl' into move_cluster_write_m…
andy31415 Mar 20, 2023
497c8a4
Some fixes
andy31415 Mar 20, 2023
eaa872b
Fix conditional in requires_timed_write
andy31415 Mar 20, 2023
014576e
Merge branch 'timed_write_attribute_in_idl' into move_cluster_write_m…
andy31415 Mar 20, 2023
4546385
Most codegen looks ok. Java boxing logic is suspect still
andy31415 Mar 20, 2023
aae7182
More updates, output idential EXCEPT types for boxing
andy31415 Mar 20, 2023
8985670
Increase 1000 to 10000 to match original template
andy31415 Mar 20, 2023
6e5cbaa
Fix byte count comparison when long starts to take effect
andy31415 Mar 20, 2023
9955422
Fix length of underlying bitmap type sizing
andy31415 Mar 20, 2023
33e70ae
Fixed files, they are IDENTICAL
andy31415 Mar 20, 2023
04f6c3d
Merge branch 'master' into move_cluster_write_mapping_to_jinja
andreilitvin Mar 21, 2023
cdc59f3
Integrate java-jni and java-class since build rules are different bet…
andreilitvin Mar 21, 2023
ad8d6d1
Fix python syntax
andreilitvin Mar 21, 2023
be476c4
Merge branch 'master' into move_cluster_write_mapping_to_jinja
andreilitvin Mar 21, 2023
300c57b
Switch default to not have underscore
andreilitvin Mar 21, 2023
6a6bc5d
Add java codegen via jinja to zap_regen_all
andreilitvin Mar 21, 2023
58712ae
Restyle, fix restyle logic
andreilitvin Mar 21, 2023
7a89a5c
Fix duplicated generation target
andreilitvin Mar 21, 2023
80baf11
Do not attempt to zap-generate Cluster write mapping
andreilitvin Mar 21, 2023
a9e2f2b
Add golden image unit test for java codegen
andy31415 Mar 21, 2023
ad4aa7c
Add prettyfy for java output ... makes the input/output files more ob…
andy31415 Mar 21, 2023
46380e3
Remove unused variable
andy31415 Mar 22, 2023
be4088e
Fix upper/lowercase of acronyms, to be fully backwards compatible
andy31415 Mar 22, 2023
5ce0b71
Add license blurb since we checkin generated file (and maybe jinja fi…
andy31415 Mar 22, 2023
a47038f
Restyle
andy31415 Mar 22, 2023
6fc9632
Fix unit test
andy31415 Mar 22, 2023
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
1 change: 1 addition & 0 deletions .restyled.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ exclude:
- "scripts/run_codegen_targets.sh" # shellharden breaks for loops over command outputs
- "src/darwin/Framework/CHIP/zap-generated/*" # already clang-formatted by our zap tooling
- "zzz_generated/**/*" # already clang-formatted by our zap tooling
- "src/controller/java/generated/java/**/*" # not formatted: generated files


changed_paths:
Expand Down
8 changes: 4 additions & 4 deletions build/chip/chip_codegen.gni
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ template("_chip_build_time_zapgen") {
# The ".matter" file to use to start the code generation
#
# generator
# Name of the generator to use (e.g. java, cpp-app)
# Name of the generator to use (e.g. java-jni, java-class, cpp-app)
#
# outputs
# Explicit names of the expected outputs. Enforced to validate that
Expand Down Expand Up @@ -296,7 +296,7 @@ template("_chip_build_time_zapgen") {
#
# chip_codegen("java-jni-generate") {
# input = "controller-clusters.matter"
# generator = "java"
# generator = "java-jni"
#
# outputs = [
# "jni/IdentifyClient-ReadImpl.cpp",
Expand Down Expand Up @@ -358,7 +358,7 @@ template("chip_codegen") {
# The ".matter" file to use to start the code generation
#
# generator
# Name of the generator to use (e.g. java, cpp-app)
# Name of the generator to use (e.g. java-jni, java-class, cpp-app)
#
# outputs
# Explicit names of the expected outputs. Enforced to validate that
Expand Down Expand Up @@ -391,7 +391,7 @@ template("chip_codegen") {
#
# chip_codegen("java-jni-generate") {
# input = "controller-clusters.matter"
# generator = "java"
# generator = "java-jni"
#
# outputs = [
# "jni/IdentifyClient-ReadImpl.cpp",
Expand Down
2 changes: 1 addition & 1 deletion scripts/codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def write_new_data(self, relative_path: str, content: str):
help='Determines the verbosity of script output')
@click.option(
'--generator',
default='JAVA',
default='java-jni',
help='What code generator to run. The choices are: '+'|'.join(GENERATORS.keys())+'. ' +
'When using custom, provide the plugin path using `--generator custom:<path_to_plugin>:<plugin_module_name>` syntax. ' +
'For example, `--generator custom:./my_plugin:my_plugin_module` will load `./my_plugin/my_plugin_module/__init.py__` ' +
Expand Down
6 changes: 4 additions & 2 deletions scripts/pregenerate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
from typing import Iterator, List, Optional

from .types import IdlFileType, InputIdlFile
from .using_codegen import CodegenBridgePregenerator, CodegenCppAppPregenerator, CodegenJavaPregenerator
from .using_codegen import (CodegenBridgePregenerator, CodegenCppAppPregenerator, CodegenJavaClassPregenerator,
CodegenJavaJNIPregenerator)
from .using_zap import ZapApplicationPregenerator


Expand Down Expand Up @@ -77,7 +78,8 @@ def FindPregenerationTargets(sdk_root: str, filter: TargetFilter, runner):
generators = [
# Jinja-based codegen
CodegenBridgePregenerator(sdk_root),
CodegenJavaPregenerator(sdk_root),
CodegenJavaJNIPregenerator(sdk_root),
CodegenJavaClassPregenerator(sdk_root),
CodegenCppAppPregenerator(sdk_root),

# ZAP codegen
Expand Down
19 changes: 17 additions & 2 deletions scripts/pregenerate/using_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def CreateTarget(self, idl: InputIdlFile, runner):
return CodegenTarget(sdk_root=self.sdk_root, idl=idl, generator="bridge", runner=runner)


class CodegenJavaPregenerator:
class CodegenJavaJNIPregenerator:
"""Pregeneration logic for "java" codegen.py outputs"""

def __init__(self, sdk_root):
Expand All @@ -85,7 +85,22 @@ def Accept(self, idl: InputIdlFile):
return idl.relative_path == "src/controller/data_model/controller-clusters.matter"

def CreateTarget(self, idl: InputIdlFile, runner):
return CodegenTarget(sdk_root=self.sdk_root, idl=idl, generator="java", runner=runner)
return CodegenTarget(sdk_root=self.sdk_root, idl=idl, generator="java-jni", runner=runner)


class CodegenJavaClassPregenerator:
"""Pregeneration logic for "java" codegen.py outputs"""

def __init__(self, sdk_root):
self.sdk_root = sdk_root

def Accept(self, idl: InputIdlFile):
# Java is highly specific, a single path is acceptable for dynamic
# bridge codegen
return idl.relative_path == "src/controller/data_model/controller-clusters.matter"

def CreateTarget(self, idl: InputIdlFile, runner):
return CodegenTarget(sdk_root=self.sdk_root, idl=idl, generator="java-class", runner=runner)


class CodegenCppAppPregenerator:
Expand Down
1 change: 1 addition & 0 deletions scripts/py_matter_idl/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ pw_python_package("matter_idl") {
"matter_idl/tests/outputs/several_clusters/bridge/SecondServer.h",
"matter_idl/tests/outputs/several_clusters/bridge/Third.h",
"matter_idl/tests/outputs/several_clusters/bridge/ThirdServer.h",
"matter_idl/tests/outputs/several_clusters/java/ClusterWriteMapping.java",
"matter_idl/tests/outputs/several_clusters/jni/FirstClient-ReadImpl.cpp",
"matter_idl/tests/outputs/several_clusters/jni/SecondClient-ReadImpl.cpp",
"matter_idl/tests/outputs/several_clusters/jni/ThirdClient-ReadImpl.cpp",
Expand Down
1 change: 1 addition & 0 deletions scripts/py_matter_idl/files.gni
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ matter_idl_generator_templates = [
"${chip_root}/scripts/py_matter_idl/matter_idl/generators/bridge/BridgeClustersGlobalStructs.jinja",
"${chip_root}/scripts/py_matter_idl/matter_idl/generators/java/ChipClustersCpp.jinja",
"${chip_root}/scripts/py_matter_idl/matter_idl/generators/java/ChipClustersRead.jinja",
"${chip_root}/scripts/py_matter_idl/matter_idl/generators/java/ClusterWriteMapping.jinja",
"${chip_root}/scripts/py_matter_idl/matter_idl/generators/cpp/application/CallbackStubSource.jinja",
"${chip_root}/scripts/py_matter_idl/matter_idl/generators/cpp/application/PluginApplicationCallbacksHeader.jinja",
]
Expand Down
28 changes: 28 additions & 0 deletions scripts/py_matter_idl/matter_idl/generators/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,31 @@ def normalize_acronyms(s: str) -> str:
return s.replace('WiFi', 'Wifi').replace('WI_FI', 'WIFI')


def lowfirst(s: str) -> str:
"""Make the first letter lowercase. """
return s[0].lower() + s[1:]


def upfirst(s: str) -> str:
"""Make the first letter uppercase """
return s[0].upper() + s[1:]


def lowfirst_except_acronym(s: str) -> str:
"""Make the first letter lowercase assuming the string is already in
CamelCase.

Differs from lowfirst because it checks the string for starting with
several uppercase, which is the case for acronyms (HVAC, ACL, WIFI),
in which case it will NOT lowercase first
"""
if len(s) >= 2:
if s[1].isupper():
return s

return lowfirst(s)


def RegisterCommonFilters(filtermap):
"""
Register filters that are NOT considered platform-generator specific.
Expand All @@ -42,3 +67,6 @@ def RegisterCommonFilters(filtermap):
filtermap['spinalcase'] = stringcase.spinalcase

filtermap['normalize_acronyms'] = normalize_acronyms
filtermap['lowfirst'] = lowfirst
filtermap['lowfirst_except_acronym'] = lowfirst_except_acronym
filtermap['upfirst'] = upfirst
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
*
* Copyright (c) 2023 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package chip.devicecontroller;

import chip.clusterinfo.CommandParameterInfo;
import chip.clusterinfo.InteractionInfo;
import chip.devicecontroller.ChipClusters.DefaultClusterCallback;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class ClusterWriteMapping {
public Map<String, Map<String, InteractionInfo>> getWriteAttributeMap() {
Map<String, Map<String, InteractionInfo>> writeAttributeMap = new HashMap<>();

{%- for cluster in clientClusters | sort(attribute='code') %}
{%- set typeLookup = idl | createLookupContext(cluster) %}
Map<String, InteractionInfo> write{{cluster.name}}InteractionInfo = new LinkedHashMap<>();
{%- for attribute in cluster.attributes | sort(attribute='name') | attributesWithCallback(typeLookup) %}
{#- TODO: add support for struct-typed attributes -#}
{% if not attribute.definition.is_list and attribute.is_writable %}
Map<String, CommandParameterInfo> write{{cluster.name}}{{attribute.definition.name | upfirst}}CommandParams = new LinkedHashMap<String, CommandParameterInfo>();
{%- set encodable = attribute.definition | asEncodable(typeLookup) %}
CommandParameterInfo {{cluster.name | lowfirst_except_acronym}}{{attribute.definition.name | lowfirst_except_acronym}}CommandParameterInfo =
new CommandParameterInfo(
"value",
{{ encodable.boxed_java_type }}.class, {# {{asJavaType type null parent.parent.name removeGenericType=true}}.class, #}
{{ encodable.boxed_java_type }}.class {# {{asJavaType type null parent.parent.name underlyingType=true}}.class #}
);
write{{cluster.name}}{{attribute.definition.name | upfirst}}CommandParams.put(
"value",
{{cluster.name | lowfirst_except_acronym}}{{attribute.definition.name | lowfirst_except_acronym}}CommandParameterInfo
);
InteractionInfo write{{cluster.name}}{{attribute.definition.name | upfirst}}AttributeInteractionInfo = new InteractionInfo(
(cluster, callback, commandArguments) -> {
((ChipClusters.{{cluster.name}}Cluster) cluster).write{{attribute.definition.name | upfirst}}Attribute(
(DefaultClusterCallback) callback,
({{ encodable.boxed_java_type }}) commandArguments.get("value")
{%- if attribute.requires_timed_write -%}, 10000 {% endif %}
);
},
() -> new ClusterInfoMapping.DelegatedDefaultClusterCallback(),
write{{cluster.name}}{{attribute.definition.name | upfirst}}CommandParams
);
write{{cluster.name}}InteractionInfo.put("write{{attribute.definition.name | upfirst}}Attribute", write{{cluster.name}}{{attribute.definition.name | upfirst}}AttributeInteractionInfo);
{%- endif %}
{%- endfor %}
writeAttributeMap.put("{{cluster.name | lowfirst_except_acronym}}", write{{cluster.name}}InteractionInfo);
{%- endfor -%}

return writeAttributeMap;
}
}
34 changes: 32 additions & 2 deletions scripts/py_matter_idl/matter_idl/generators/java/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,9 +356,11 @@ def CanGenerateSubscribe(attr: Attribute, lookup: TypeLookupContext) -> bool:
return not lookup.is_struct_type(attr.definition.data_type.name)


class JavaGenerator(CodeGenerator):
class __JavaCodeGenerator(CodeGenerator):
"""
Generation of java code for matter.
Code generation for java-specific files.

Registers filters used by all java generators.
"""

def __init__(self, storage: GeneratorStorage, idl: Idl, **kargs):
Expand All @@ -378,6 +380,13 @@ def __init__(self, storage: GeneratorStorage, idl: Idl, **kargs):
self.jinja_env.filters['createLookupContext'] = CreateLookupContext
self.jinja_env.filters['canGenerateSubscribe'] = CanGenerateSubscribe


class JavaJNIGenerator(__JavaCodeGenerator):
"""Generates JNI java files (i.e. C++ source/headers)."""

def __init__(self, *args, **kargs):
super().__init__(*args, **kargs)

def internal_render_all(self):
"""
Renders .CPP files required for JNI support.
Expand Down Expand Up @@ -406,3 +415,24 @@ def internal_render_all(self):
'typeLookup': TypeLookupContext(self.idl, cluster),
}
)


class JavaClassGenerator(__JavaCodeGenerator):
"""Generates .java files """

def __init__(self, *args, **kargs):
super().__init__(*args, **kargs)

def internal_render_all(self):
"""
Renders .java files required for java matter support
"""

self.internal_render_one_output(
template_path="java/ClusterWriteMapping.jinja",
output_file_name="java/chip/devicecontroller/ClusterWriteMapping.java",
vars={
'idl': self.idl,
'clientClusters': [c for c in self.idl.clusters if c.side == ClusterSide.CLIENT],
}
)
14 changes: 9 additions & 5 deletions scripts/py_matter_idl/matter_idl/generators/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

from matter_idl.generators.bridge import BridgeGenerator
from matter_idl.generators.cpp.application import CppApplicationGenerator
from matter_idl.generators.java import JavaGenerator
from matter_idl.generators.java import JavaClassGenerator, JavaJNIGenerator


class CodeGenerator(enum.Enum):
Expand All @@ -26,14 +26,17 @@ class CodeGenerator(enum.Enum):
the simple enum value (user friendly and can be a command line input)
into underlying generators.
"""
JAVA = enum.auto()
JAVA_JNI = enum.auto()
JAVA_CLASS = enum.auto()
BRIDGE = enum.auto()
CPP_APPLICATION = enum.auto()
CUSTOM = enum.auto()

def Create(self, *args, **kargs):
if self == CodeGenerator.JAVA:
return JavaGenerator(*args, **kargs)
if self == CodeGenerator.JAVA_JNI:
return JavaJNIGenerator(*args, **kargs)
elif self == CodeGenerator.JAVA_CLASS:
return JavaClassGenerator(*args, **kargs)
elif self == CodeGenerator.BRIDGE:
return BridgeGenerator(*args, **kargs)
elif self == CodeGenerator.CPP_APPLICATION:
Expand Down Expand Up @@ -63,7 +66,8 @@ def FromString(name):
# to uniquely identify them when running command line tools or
# executing tests
GENERATORS = {
'java': CodeGenerator.JAVA,
'java-jni': CodeGenerator.JAVA_JNI,
'java-class': CodeGenerator.JAVA_CLASS,
'bridge': CodeGenerator.BRIDGE,
'cpp-app': CodeGenerator.CPP_APPLICATION,
'custom': CodeGenerator.CUSTOM,
Expand Down
8 changes: 5 additions & 3 deletions scripts/py_matter_idl/matter_idl/test_generators.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from matter_idl.generators import GeneratorStorage
from matter_idl.generators.bridge import BridgeGenerator
from matter_idl.generators.cpp.application import CppApplicationGenerator
from matter_idl.generators.java import JavaGenerator
from matter_idl.generators.java import JavaClassGenerator, JavaJNIGenerator
from matter_idl.matter_idl_types import Idl

TESTS_DIR = os.path.join(os.path.dirname(__file__), "tests")
Expand Down Expand Up @@ -116,8 +116,10 @@ def add_test_cases(self, yaml_test_case_dict):
self.test_cases.append(test_case)

def _create_generator(self, storage: GeneratorStorage, idl: Idl):
if self.generator_name.lower() == 'java':
return JavaGenerator(storage, idl)
if self.generator_name.lower() == 'java-jni':
return JavaJNIGenerator(storage, idl)
if self.generator_name.lower() == 'java-class':
return JavaClassGenerator(storage, idl)
if self.generator_name.lower() == 'bridge':
return BridgeGenerator(storage, idl)
if self.generator_name.lower() == 'cpp-app':
Expand Down
6 changes: 5 additions & 1 deletion scripts/py_matter_idl/matter_idl/tests/available_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# - input_file is the input IDL
# - output_file/golden_path are the expected output file names
# and the expected content for those output files.
java:
java-jni:
inputs/simple_attribute.matter:
jni/MyClusterClient-ReadImpl.cpp: outputs/simple_attribute/jni/MyClusterClient-ReadImpl.cpp
jni/MyClusterClient-InvokeSubscribeImpl.cpp: outputs/simple_attribute/jni/MyClusterClient-InvokeSubscribeImpl.cpp
Expand All @@ -35,6 +35,10 @@ java:
jni/MyClusterClient-ReadImpl.cpp: outputs/optional_argument/jni/MyClusterClient-ReadImpl.cpp
jni/MyClusterClient-InvokeSubscribeImpl.cpp: outputs/optional_argument/jni/MyClusterClient-InvokeSubscribeImpl.cpp

java-class:
inputs/several_clusters.matter:
java/chip/devicecontroller/ClusterWriteMapping.java: outputs/several_clusters/java/ClusterWriteMapping.java

bridge:
inputs/simple_attribute.matter:
bridge/BridgeClustersImpl.h: outputs/simple_attribute/bridge/BridgeClustersImpl.h
Expand Down
Loading