Skip to content

Commit 57b29e8

Browse files
authored
Leverage Template literals to replace dot (#1297)
This PR replaces the doT template engine with native JavaScript template literals for generating ROS2 message/service wrapper classes. The change migrates from external template files to pure JavaScript functions, improving maintainability and performance. - Removed dependency on doT template engine and replaced with native JavaScript template literals - Created new template generator functions for messages, services, actions, and service events - Updated the IDL generator to use the new template functions instead of doT templates **Reference**: - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals Fix: #1297
1 parent 2622779 commit 57b29e8

File tree

10 files changed

+1265
-948
lines changed

10 files changed

+1265
-948
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
"bindings": "^1.5.0",
7979
"compare-versions": "^6.1.1",
8080
"debug": "^4.4.0",
81-
"dot": "^1.1.3",
8281
"fs-extra": "^11.2.0",
8382
"json-bigint": "^1.0.0",
8483
"node-addon-api": "^8.3.1",

rosidl_gen/idl_generator.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,17 @@
1414

1515
'use strict';
1616

17-
const dot = require('dot');
1817
const fse = require('fs-extra');
1918
const path = require('path');
2019
const parser = require('../rosidl_parser/rosidl_parser.js');
2120
const actionMsgs = require('./action_msgs.js');
2221
const DistroUtils = require('../lib/distro.js');
22+
const generateMessage = require('./templates/message-template.js');
23+
const generateService = require('./templates/service-template.js');
24+
const generateAction = require('./templates/action-template.js');
25+
const generateServiceEvent = require('./templates/service-event-template.js');
2326

24-
dot.templateSettings.strip = false;
25-
dot.log = process.env.RCLNODEJS_LOG_VERBOSE || false;
2627
const isDebug = !!process.argv.find((arg) => arg === '--debug');
27-
const dots = dot.process({
28-
path: path.join(__dirname, '../rosidl_gen/templates'),
29-
});
3028

3129
/**
3230
* Output generated code to disk. Do not overwrite
@@ -53,7 +51,7 @@ async function generateServiceJSStruct(
5351
'__' +
5452
serviceInfo.interfaceName +
5553
'.js';
56-
const generatedSrvCode = dots.service({ serviceInfo: serviceInfo });
54+
const generatedSrvCode = generateService({ serviceInfo: serviceInfo });
5755

5856
// We are going to only generate the service JavaScript file if it meets one
5957
// of the followings:
@@ -74,7 +72,7 @@ async function generateServiceJSStruct(
7472

7573
async function generateServiceEventMsg(serviceInfo, dir) {
7674
const fileName = serviceInfo.interfaceName + '.msg';
77-
const generatedEvent = dots.service_event({ serviceInfo: serviceInfo });
75+
const generatedEvent = generateServiceEvent({ serviceInfo: serviceInfo });
7876

7977
return writeGeneratedCode(dir, fileName, generatedEvent).then(() => {
8078
serviceInfo.interfaceName += '_Event';
@@ -107,7 +105,7 @@ async function generateServiceEventJSStruct(msgInfo, dir) {
107105
// const AddTwoInts_RequestWrapper = require('../../generated/example_interfaces/example_interfaces__srv__AddTwoInts_Request.js');
108106
// const AddTwoInts_ResponseWrapper = require('../../generated/example_interfaces/example_interfaces__srv__AddTwoInts_Response.js');
109107
msgInfo.isServiceEvent = true;
110-
const generatedCode = dots.message({
108+
const generatedCode = generateMessage({
111109
messageInfo: msgInfo,
112110
spec: spec,
113111
json: JSON.stringify(spec, null, ' '),
@@ -135,7 +133,7 @@ function generateMessageJSStructFromSpec(messageInfo, dir, spec) {
135133
spec.msgName +
136134
'.js';
137135

138-
const generatedCode = dots.message({
136+
const generatedCode = generateMessage({
139137
messageInfo: messageInfo,
140138
spec: spec,
141139
json: JSON.stringify(spec, null, ' '),
@@ -275,7 +273,7 @@ async function generateActionJSStruct(actionInfo, dir) {
275273
'__' +
276274
actionInfo.interfaceName +
277275
'.js';
278-
const generatedCode = dots.action({ actionInfo: actionInfo });
276+
const generatedCode = generateAction({ actionInfo: actionInfo });
279277
dir = path.join(dir, actionInfo.pkgName);
280278
const action = writeGeneratedCode(dir, fileName, generatedCode);
281279

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) 2025, The Robot Web Tools Contributors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
function generateAction(data) {
16+
const actionInfo = data.actionInfo;
17+
const className = `${actionInfo.pkgName}__${actionInfo.subFolder}__${actionInfo.interfaceName}`;
18+
19+
return `// This file is automatically generated by rclnodejs
20+
//
21+
// *** DO NOT EDIT directly
22+
//
23+
24+
'use strict';
25+
26+
class ${className} {
27+
static get Goal() {
28+
return require('./${className}_Goal.js');
29+
}
30+
31+
static get Result() {
32+
return require('./${className}_Result.js');
33+
}
34+
35+
static get Feedback() {
36+
return require('./${className}_Feedback.js');
37+
}
38+
39+
static get impl() {
40+
return {
41+
get SendGoalService() {
42+
return require('./${className}_SendGoal.js');
43+
},
44+
get GetResultService() {
45+
return require('./${className}_GetResult.js');
46+
},
47+
get FeedbackMessage() {
48+
return require('./${className}_FeedbackMessage.js');
49+
},
50+
get CancelGoal() {
51+
return require('../action_msgs/action_msgs__srv__CancelGoal.js');
52+
},
53+
get GoalStatusArray() {
54+
return require('../action_msgs/action_msgs__msg__GoalStatusArray.js');
55+
}
56+
};
57+
}
58+
59+
static type() {
60+
return {pkgName: '${actionInfo.pkgName}', subFolder: '${actionInfo.subFolder}', interfaceName: '${actionInfo.interfaceName}'};
61+
}
62+
}
63+
64+
module.exports = ${className};
65+
`;
66+
}
67+
68+
module.exports = generateAction;

rosidl_gen/templates/action.dot

Lines changed: 0 additions & 50 deletions
This file was deleted.

0 commit comments

Comments
 (0)