Skip to content

Commit 58a3d85

Browse files
dhchandwgemini-code-assist[bot]Copilot
authored
Add support for static template generation control (#1674)
* Add support for static template generation control - Add 'static' boolean flag to individual templates to mark them as static content - Add 'generateStaticTemplates' generator option to control default behavior - Static templates are skipped when generateStaticTemplates is false for the session - Session-level .zap file settings can override the generator default * Apply suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot <[email protected]>
1 parent 62306d7 commit 58a3d85

File tree

13 files changed

+8118
-24
lines changed

13 files changed

+8118
-24
lines changed

apack.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "Graphical configuration tool for application and libraries based on Zigbee Cluster Library.",
55
"path": [".", "node_modules/.bin/", "ZAP.app/Contents/MacOS"],
66
"requiredFeatureLevel": "apack.core:9",
7-
"featureLevel": 108,
7+
"featureLevel": 109,
88
"uc.triggerExtension": "zap",
99
"uc.sdkProvidedProperties": "zcl.matterZclJsonFile,zcl.matterTemplateJsonFile,zcl.zigbeeZclJsonFile,zcl.zigbeeTemplateJsonFile",
1010
"executable": {

docs/sdk-integration.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ The `templates` key contained in the `gen-templates.json` file above, is an arra
7979
| name | string | Human readable name of the template. Mostly used in logging and menu items. |
8080
| output | string | Name of the output file generated. May contain replacement patterns (see below). |
8181
| iterator | string | If this template produces multiple files, iterating over certain object, then this field will be present. Possible values are `availableCluster`, `selectedCluster`,`selectedClientCluster`, `selectedServerCluster`. |
82+
| static | string | If set to the string 'true', marks this template as a static template. Static templates will not generate if `generateStaticTemplates` is false for the session. |
8283

8384
The _replacement pattern_ inside the output key, comes handy when iterator key is used and defines how each generated file will be named. Replacement patterns are in a format of `{key}` or `{key:modifier}`. The `key` can be any usual key that the iterated object provides. For example, if you iterate over cluster, these can be `code`, `name`, `description`, `define` and all the usual keys that a cluster supports. So if your output contains `{code}` then this pattern will be replaced by the actual cluster code.
8485

@@ -105,6 +106,7 @@ Following table lists generator options supported by the template generator cate
105106
| postProcessSingle | a string, representing a command to execute for each individual file appended in a single command line. This would be typically used by commands or scripts that clean up the generated files, and can only take one file name at a time as an argument. |
106107
| postProcessConditionalFile | a path, representing a file. If this file does not exist, then a specified post-process action will not get executed. |
107108
| routeErrToOut | a boolean flag. If it's set to true, then any stderr from the post-process will be routed to stdout. This is due that a driving process sometimes has trouble dealing with both stdout and stderr, so this flag might help you preserve the logs. |
109+
| generateStaticTemplates | string | A string flag ('true'/'false'). The default for whether static templates are generated. If 'false', they are not. A session-key in the .zap file can override this default. |
108110

109111
## Template key: override
110112

src-electron/generator/generation-engine.js

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -204,19 +204,42 @@ async function recordTemplatesPackage(context, isTopLevelPackageInSync) {
204204
template.name
205205
).then((id) => {
206206
// We loaded the individual file, now we add options
207+
let optionPromises = []
208+
// Handle iterator option
207209
if (template.iterator) {
208-
return queryPackage.insertOptionsKeyValues(
209-
context.db,
210-
id,
211-
dbEnum.packageOptionCategory.outputOptions,
212-
[
213-
{
214-
code: 'iterator',
215-
label: template.iterator
216-
}
217-
]
210+
optionPromises.push(
211+
queryPackage.insertOptionsKeyValues(
212+
context.db,
213+
id,
214+
dbEnum.packageOptionCategory.outputOptions,
215+
[
216+
{
217+
code: 'iterator',
218+
label: template.iterator
219+
}
220+
]
221+
)
222+
)
223+
}
224+
// Handle static option
225+
// If static is defined and true, then this template is only generated when generateStaticTemplates is true
226+
// If static doesn't exist, we treat it as false
227+
if (template.static) {
228+
optionPromises.push(
229+
queryPackage.insertOptionsKeyValues(
230+
context.db,
231+
id,
232+
dbEnum.packageOptionCategory.generator,
233+
[
234+
{
235+
code: 'static',
236+
label: template.static
237+
}
238+
]
239+
)
218240
)
219241
}
242+
return Promise.all(optionPromises)
220243
})
221244
)
222245
}
@@ -718,6 +741,19 @@ async function generateAllTemplates(
718741
let generationTemplates = []
719742
let overridePath = null
720743

744+
// generateStaticTemplates can be a session-key, if it exists then use it from session key otherwise use it from generatorOptions
745+
let generateStaticTemplates = await querySession.getSessionKeyValue(
746+
genResult.db,
747+
genResult.sessionId,
748+
dbEnum.sessionKey.generateStaticTemplates
749+
)
750+
if (generateStaticTemplates == null) {
751+
generateStaticTemplates = genResult.generatorOptions.generateStaticTemplates
752+
}
753+
// Convert string values to proper boolean - generateStaticTemplates defaults to true unless explicitly set to false
754+
generateStaticTemplates =
755+
generateStaticTemplates !== 'false' && generateStaticTemplates !== false
756+
721757
let hb = templateEngine.hbInstance()
722758
let context = {
723759
db: genResult.db,
@@ -736,8 +772,17 @@ async function generateAllTemplates(
736772
pkg.iterator = opt.optionLabel
737773
}
738774
})
775+
let generatorOptions = await queryPackage.selectAllOptionsValues(
776+
genResult.db,
777+
pkg.id,
778+
dbEnum.packageOptionCategory.generator
779+
)
780+
generatorOptions.forEach((opt) => {
781+
if (opt.optionCode == 'static') {
782+
pkg.static = opt.optionLabel
783+
}
784+
})
739785
}
740-
741786
// First extract overridePath if one exists, as we need to
742787
// pass it to the generation.
743788
packages.forEach((singlePkg) => {
@@ -778,6 +823,10 @@ async function generateAllTemplates(
778823
// Next prepare the templates
779824
packages.forEach((singlePkg) => {
780825
if (singlePkg.type == dbEnum.packageType.genSingleTemplate) {
826+
// Skip static templates if generateStaticTemplates is false
827+
if (!generateStaticTemplates && singlePkg.static === 'true') {
828+
return
829+
}
781830
if (options.generateOnly == null) {
782831
generationTemplates.push(singlePkg)
783832
} else if (

src-shared/db-enum.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ exports.sessionKey = {
105105
filePath: 'filePath',
106106
ideProjectPath: 'ideProjectPath',
107107
informationText: 'informationText',
108-
disableComponentToggling: 'disableComponentToggling'
108+
disableComponentToggling: 'disableComponentToggling',
109+
generateStaticTemplates: 'generateStaticTemplates'
109110
}
110111

111112
exports.pathRelativity = {
@@ -145,7 +146,8 @@ exports.generatorOptions = {
145146
postProcessConditionalFile: 'postProcessConditionalFile',
146147
enabled: 'enabled',
147148
shareClusterStatesAcrossEndpoints: 'shareClusterStatesAcrossEndpoints',
148-
disableUcComponentOnZclClusterUpdate: 'disableUcComponentOnZclClusterUpdate'
149+
disableUcComponentOnZclClusterUpdate: 'disableUcComponentOnZclClusterUpdate',
150+
generateStaticTemplates: 'generateStaticTemplates'
149151
}
150152

151153
exports.sessionOption = {

test/gen-matter-1.test.js

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ test(
184184
queryPackage
185185
.selectAllOptionsValues(db, pkgId, 'generator')
186186
.then((generatorConfigurations) => {
187-
expect(generatorConfigurations.length).toBe(1)
187+
expect(generatorConfigurations.length).toBe(2)
188188
expect(generatorConfigurations[0].optionCode).toBe(
189189
'disableUcComponentOnZclClusterUpdate'
190190
)
@@ -355,3 +355,136 @@ test(
355355
},
356356
testUtil.timeout.long()
357357
)
358+
359+
test(
360+
'Zap file generation when generateStaticTemplates is false in zap file',
361+
async () => {
362+
let sessionId = await querySession.createBlankSession(db)
363+
364+
await importJs.importDataFromFile(
365+
db,
366+
testUtil.matterTestFile.matterTestNoStatic,
367+
{
368+
sessionId: sessionId
369+
}
370+
)
371+
372+
// Verify that the generateStaticTemplates session-key is actually false
373+
let generateStaticTemplates = await querySession.getSessionKeyValue(
374+
db,
375+
sessionId,
376+
'generateStaticTemplates'
377+
)
378+
expect(generateStaticTemplates).toBe('false')
379+
380+
let genResult = await genEngine.generate(
381+
db,
382+
sessionId,
383+
templateContext.packageId,
384+
{},
385+
{ disableDeprecationWarnings: true }
386+
)
387+
388+
expect(genResult).not.toBeNull()
389+
expect(genResult.partial).toBeFalsy()
390+
expect(genResult.content).not.toBeNull()
391+
392+
// Verify that only non-static templates are generated
393+
let contentKeys = Object.keys(genResult.content)
394+
expect(contentKeys).toHaveLength(2)
395+
expect(contentKeys).toContain('endpoints.out')
396+
expect(contentKeys).toContain('endpoint-config.c')
397+
},
398+
testUtil.timeout.long()
399+
)
400+
401+
test(
402+
'Zap file generation when generateStaticTemplates is true in zap file but false in generator options',
403+
async () => {
404+
let sessionId = await querySession.createBlankSession(db)
405+
406+
await importJs.importDataFromFile(
407+
db,
408+
testUtil.matterTestFile.matterTestWithStatic,
409+
{
410+
sessionId: sessionId
411+
}
412+
)
413+
414+
// Verify that the generateStaticTemplates session-key is true
415+
let generateStaticTemplates = await querySession.getSessionKeyValue(
416+
db,
417+
sessionId,
418+
'generateStaticTemplates'
419+
)
420+
expect(generateStaticTemplates).toBe('true')
421+
422+
let genResult = await genEngine.generate(
423+
db,
424+
sessionId,
425+
templateContext.packageId,
426+
{},
427+
{ disableDeprecationWarnings: true }
428+
)
429+
430+
expect(genResult).not.toBeNull()
431+
expect(genResult.partial).toBeFalsy()
432+
expect(genResult.content).not.toBeNull()
433+
434+
// Verify that all templates are generated
435+
let contentKeys = Object.keys(genResult.content)
436+
expect(contentKeys).toHaveLength(8)
437+
},
438+
testUtil.timeout.long()
439+
)
440+
441+
test(
442+
'Zap file generation with blank session with gen-template having generateStaticTemplates as false',
443+
async () => {
444+
// Load the matterNoStatic template context
445+
let noStaticTemplateContext = await genEngine.loadTemplates(
446+
db,
447+
testUtil.testTemplate.matterNoStatic
448+
)
449+
450+
expect(noStaticTemplateContext.crc).not.toBeNull()
451+
expect(noStaticTemplateContext.templateData).not.toBeNull()
452+
expect(noStaticTemplateContext.packageId).not.toBeNull()
453+
454+
// Create a blank session
455+
let sessionId = await querySession.createBlankSession(db)
456+
457+
// Query generator options from the noStatic template
458+
let genOptions = await queryPackage.selectAllOptionsValues(
459+
db,
460+
noStaticTemplateContext.packageId,
461+
dbEnum.packageOptionCategory.generator
462+
)
463+
464+
// Reduce the long array from query into a single object
465+
let templateGeneratorOptions = genOptions.reduce((acc, current) => {
466+
acc[current.optionCode] = current.optionLabel
467+
return acc
468+
}, {})
469+
470+
// Generate using the matterNoStatic template context
471+
let genResult = await genEngine.generate(
472+
db,
473+
sessionId,
474+
noStaticTemplateContext.packageId,
475+
templateGeneratorOptions,
476+
{ disableDeprecationWarnings: true }
477+
)
478+
479+
expect(genResult).not.toBeNull()
480+
expect(genResult.partial).toBeFalsy()
481+
expect(genResult.content).not.toBeNull()
482+
483+
// Verify that only non-static templates are generated
484+
let contentKeys = Object.keys(genResult.content)
485+
expect(contentKeys).toHaveLength(2)
486+
expect(contentKeys).toContain('endpoints.out')
487+
expect(contentKeys).toContain('endpoint-config.c')
488+
},
489+
testUtil.timeout.long()
490+
)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
{
2+
"name": "Matter test template",
3+
"version": "test-matter",
4+
"category": "matter",
5+
"options": {
6+
"testOption": {
7+
"code1": "label1",
8+
"code2": "label2",
9+
"code3": "label3",
10+
"code4": "label4",
11+
"code5": "label5"
12+
},
13+
"externalOption": "externalOptions.json",
14+
"cli": "cli.json",
15+
"generator": {
16+
"disableUcComponentOnZclClusterUpdate": "true",
17+
"generateStaticTemplates": "false"
18+
}
19+
},
20+
"zcl": {
21+
"event": {
22+
"testEventExtension1": {
23+
"type": "text",
24+
"configurability": "hidden",
25+
"globalDefault": "defGlob",
26+
"label": "Test event extensions",
27+
"defaults": [
28+
{
29+
"clusterCode": "0x9999",
30+
"eventCode": "0x0001",
31+
"value": "defHello"
32+
}
33+
]
34+
}
35+
}
36+
},
37+
"helpers": ["helper-chip.js", "external-addon-helper.js"],
38+
"templates": [
39+
{
40+
"path": "simple-test.zapt",
41+
"name": "Simple test template",
42+
"output": "simple-test.h",
43+
"static": "true"
44+
},
45+
{
46+
"path": "sdk-ext.zapt",
47+
"name": "SDK extension test",
48+
"output": "sdk-ext.txt",
49+
"static": "true"
50+
},
51+
{
52+
"path": "feature-map.zapt",
53+
"name": "Feature map test template",
54+
"output": "feature-map.h",
55+
"static": "true"
56+
},
57+
{
58+
"path": "device-types.zapt",
59+
"name": "Device types",
60+
"output": "device-types.txt",
61+
"static": "true"
62+
},
63+
{
64+
"path": "endpoint-config.zapt",
65+
"name": "Endpoint Configuration",
66+
"output": "endpoint-config.c"
67+
},
68+
{
69+
"path": "events.zapt",
70+
"name": "Events",
71+
"output": "events.out",
72+
"static": "true"
73+
},
74+
{
75+
"path": "endpoints.zapt",
76+
"name": "Endpoints",
77+
"output": "endpoints.out"
78+
},
79+
{
80+
"path": "chip-tool-helpers.zapt",
81+
"name": "Helpers in chip-tool",
82+
"output": "chip-tool-helpers.txt",
83+
"static": "true"
84+
}
85+
]
86+
}

0 commit comments

Comments
 (0)