diff --git a/packages/omgidl-parser/src/IDLNodeProcessor.ts b/packages/omgidl-parser/src/IDLNodeProcessor.ts index bee5945..1141b00 100644 --- a/packages/omgidl-parser/src/IDLNodeProcessor.ts +++ b/packages/omgidl-parser/src/IDLNodeProcessor.ts @@ -4,7 +4,13 @@ import { MessageDefinitionField, } from "@foxglove/message-definition"; -import { RawIdlDefinition, AnyIDLNode, ConstantNode } from "./types"; +import { + RawIdlDefinition, + AnyIDLNode, + ConstantNode, + AnnotatedMessageDefinition, + AnnotatedMessageDefinitionField, +} from "./types"; const numericTypeMap: Record = { "unsigned short": "uint16", @@ -53,6 +59,7 @@ export class IDLNodeProcessor { this.map = new Map(); this.buildMap(); } + /** Initializes map of IDL nodes to their scoped namespaces */ buildMap(): void { for (const definition of this.definitions) { @@ -198,7 +205,7 @@ export class IDLNodeProcessor { } /** Resolve struct-members that refer to complex types as complex */ - resolveComplexTypes(): void { + resolveStructMemberComplexity(): void { // resolve non-primitive struct member types for (const [scopedIdentifier, node] of this.map.entries()) { if (node.declarator !== "struct-member") { @@ -228,11 +235,17 @@ export class IDLNodeProcessor { ...partialDef } = typeNode; - this.map.set(scopedIdentifier, { + const newNode = { ...node, ...partialDef, - annotations: { ...typedefAnnotations, ...node.annotations }, - }); + }; + + const annotations = { ...typedefAnnotations, ...node.annotations }; + if (Object.keys(annotations).length > 0) { + newNode.annotations = annotations; + } + + this.map.set(scopedIdentifier, newNode); } else if (typeNode.declarator === "struct") { this.map.set(scopedIdentifier, { ...node, isComplex: true }); } else { @@ -243,47 +256,45 @@ export class IDLNodeProcessor { } } - /** Convert to Message Definitions for serialization and usage in foxglove studio's Raw Message panel. Returned in order of original definitions*/ toMessageDefinitions(): MessageDefinition[] { - const messageDefinitions: MessageDefinition[] = []; + const idlMsgDefs = this.toAnnotatedMessageDefinitions(); + + return idlMsgDefs.map(toMessageDefinition); + } + + /** Convert to Message Definitions for serialization and usage in foxglove studio's Raw Message panel. Returned in order of original definitions*/ + toAnnotatedMessageDefinitions(): AnnotatedMessageDefinition[] { + const messageDefinitions: AnnotatedMessageDefinition[] = []; const topLevelConstantDefinitions: MessageDefinitionField[] = []; // flatten for output to message definition // Because the map entries are in original insertion order, they should reflect the original order of the definitions // This is important for ros2idl compatibility for (const [namespacedName, node] of this.map.entries()) { - if (node.declarator === "struct") { - messageDefinitions.push({ - name: namespacedName, - definitions: node.definitions - .map((def) => - this.idlNodeToMessageDefinitionField(toScopedIdentifier([namespacedName, def.name])), - ) - .filter(Boolean) as MessageDefinitionField[], - }); - } else if (node.declarator === "module") { - const fieldDefinitions = node.definitions + if ( + node.declarator === "struct" || + node.declarator === "module" || + node.declarator === "enum" + ) { + const isEnum = node.declarator === "enum"; + const members = isEnum ? node.enumerators : node.definitions; + const definitionFields = members .map((def) => - this.idlNodeToMessageDefinitionField(toScopedIdentifier([namespacedName, def.name])), - ) - .filter(Boolean) as MessageDefinitionField[]; - if (fieldDefinitions.length > 0) { - messageDefinitions.push({ - name: namespacedName, - definitions: fieldDefinitions, - }); - } - } else if (node.declarator === "enum") { - const fieldDefinitions = node.enumerators - .map((enumMember) => - this.idlNodeToMessageDefinitionField(toScopedIdentifier([namespacedName, enumMember])), + this.idlNodeToMessageDefinitionField( + toScopedIdentifier([namespacedName, typeof def === "string" ? def : def.name]), + ), ) - .filter(Boolean) as MessageDefinitionField[]; - if (fieldDefinitions.length > 0) { - messageDefinitions.push({ + .filter(Boolean) as AnnotatedMessageDefinitionField[]; + if (definitionFields.length > 0) { + const def: AnnotatedMessageDefinition = { name: namespacedName, - definitions: fieldDefinitions, - }); + definitions: definitionFields, + }; + + if (node.annotations) { + def.annotations = node.annotations; + } + messageDefinitions.push(def); } } else if (node.name === namespacedName && node.isConstant === true) { // handles top-level constants that aren't within a module @@ -303,7 +314,7 @@ export class IDLNodeProcessor { private idlNodeToMessageDefinitionField( nodeScopedIdentifier: string, - ): MessageDefinitionField | undefined { + ): AnnotatedMessageDefinitionField | undefined { const node = this.map.get(nodeScopedIdentifier); if (!node) { return undefined; @@ -333,7 +344,7 @@ export class IDLNodeProcessor { const fullMessageDef = { ...partialMessageDef, type: normalizeType(partialMessageDef.type), - } as MessageDefinitionField; + } as AnnotatedMessageDefinitionField; // avoid writing undefined to object fields if (arrayLength != undefined) { @@ -369,10 +380,24 @@ export class IDLNodeProcessor { } } + if (annotations) { + fullMessageDef.annotations = annotations; + } + return fullMessageDef; } } +// Removes `annotation` field from the Definition and DefinitionField objects +function toMessageDefinition(idlMsgDef: AnnotatedMessageDefinition): MessageDefinition { + const { definitions, annotations: _a, ...partialDef } = idlMsgDef; + const fieldDefinitions = definitions.map((def) => { + const { annotations: _an, ...partialFieldDef } = def; + return partialFieldDef; + }); + return { ...partialDef, definitions: fieldDefinitions }; +} + export function resolveScopedOrLocalNodeReference({ usedIdentifier, scopedIdentifierOfUsageNode, diff --git a/packages/omgidl-parser/src/index.ts b/packages/omgidl-parser/src/index.ts index d40afab..c169058 100644 --- a/packages/omgidl-parser/src/index.ts +++ b/packages/omgidl-parser/src/index.ts @@ -1 +1,2 @@ export * from "./parseIdl"; +export * from "./types"; diff --git a/packages/omgidl-parser/src/parseIdl.test.ts b/packages/omgidl-parser/src/parseIdl.test.ts index 72a3938..be3bc9a 100644 --- a/packages/omgidl-parser/src/parseIdl.test.ts +++ b/packages/omgidl-parser/src/parseIdl.test.ts @@ -270,6 +270,15 @@ describe("omgidl parser tests", () => { name: "short5", type: "int16", defaultValue: 5, + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { + value: 5, + }, + }, + }, }, ], name: "rosidl_parser::action::MyAction_Goal", @@ -748,28 +757,105 @@ module rosidl_parser { expect(types).toEqual([ { name: "rosidl_parser::msg::MyMessage", + annotations: { + verbatim: { + name: "verbatim", + type: "named-params", + namedParams: { + language: "comment", + text: "Documentation of MyMessage.Adjacent string literal.", + }, + }, + transfer_mode: { + name: "transfer_mode", + type: "const-param", + value: { + usesConstant: true, + name: "SHMEM_REF", + }, + }, + }, definitions: [ { defaultValue: 123, type: "uint16", name: "unsigned_short_value", isComplex: false, + annotations: { + default: { + name: "default", + namedParams: { + value: 123, + }, + type: "named-params", + }, + }, }, { type: "int32", name: "long_value", isComplex: false, + annotations: { + key: { + name: "key", + type: "no-params", + }, + range: { + name: "range", + type: "named-params", + namedParams: { + max: 10, + min: -10, + }, + }, + }, }, { type: "uint32", name: "unsigned_long_value", isComplex: false, + annotations: { + arbitrary_annotation: { + name: "arbitrary_annotation", + namedParams: { + key1: "value1", + key2: true, + key3: 0, + key4: 10, + }, + type: "named-params", + }, + key: { + name: "key", + type: "no-params", + }, + verbatim: { + name: "verbatim", + namedParams: { + language: "comment", + text: "", + }, + type: "named-params", + }, + }, }, { type: "uint32", name: "uint32_with_default", isComplex: false, defaultValue: 200, + annotations: { + id: { + name: "id", + type: "const-param", + value: 100, + }, + default: { + name: "default", + type: "const-param", + value: 200, + }, + }, }, ], }, @@ -872,87 +958,204 @@ module geometry { ); expect(types).toEqual([ { - name: "rosidl_parser::msg::MyMessage", definitions: [ { + annotations: { + default: { + name: "default", + namedParams: { + value: 19000000000, + }, + type: "named-params", + }, + }, defaultValue: 19000000000, - type: "float32", - name: "int_and_frac_with_positive_scientific", isComplex: false, + name: "int_and_frac_with_positive_scientific", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 19000000000, + }, + type: "named-params", + }, + }, defaultValue: 19000000000, - type: "float32", - name: "int_and_frac_with_explicit_positive_scientific", isComplex: false, + name: "int_and_frac_with_explicit_positive_scientific", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 1.1e-10, + }, + type: "named-params", + }, + }, defaultValue: 1.1e-10, - type: "float32", - name: "int_and_frac_with_negative_scientific", isComplex: false, + name: "int_and_frac_with_negative_scientific", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 0.00009, + }, + type: "named-params", + }, + }, defaultValue: 0.00009, - type: "float32", - name: "int_and_frac", isComplex: false, + name: "int_and_frac", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 1, + }, + type: "named-params", + }, + }, defaultValue: 1, - type: "float32", - name: "int_with_empty_frac", isComplex: false, + name: "int_with_empty_frac", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 0.1, + }, + type: "named-params", + }, + }, defaultValue: 0.1, - type: "float32", - name: "frac_only", isComplex: false, + name: "frac_only", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 900000, + }, + type: "named-params", + }, + }, defaultValue: 900000, - type: "float32", - name: "int_with_positive_scientific", isComplex: false, + name: "int_with_positive_scientific", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 900000, + }, + type: "named-params", + }, + }, defaultValue: 900000, - type: "float32", - name: "int_with_explicit_positive_scientific", isComplex: false, + name: "int_with_explicit_positive_scientific", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 0.00009, + }, + type: "named-params", + }, + }, defaultValue: 0.00009, - type: "float32", - name: "int_with_negative_scientific", isComplex: false, + name: "int_with_negative_scientific", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 8.7, + }, + type: "named-params", + }, + }, defaultValue: 8.7, - type: "float32", - name: "fixed_int_and_frac", isComplex: false, + name: "fixed_int_and_frac", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 4, + }, + type: "named-params", + }, + }, defaultValue: 4, - type: "float32", - name: "fixed_int_with_dot_only", isComplex: false, + name: "fixed_int_with_dot_only", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 0.3, + }, + type: "named-params", + }, + }, defaultValue: 0.3, - type: "float32", - name: "fixed_frac_only", isComplex: false, + name: "fixed_frac_only", + type: "float32", }, { + annotations: { + default: { + name: "default", + namedParams: { + value: 7, + }, + type: "named-params", + }, + }, defaultValue: 7, - type: "float32", - name: "fixed_int_only", isComplex: false, + name: "fixed_int_only", + type: "float32", }, ], + name: "rosidl_parser::msg::MyMessage", }, ]); }); @@ -1079,12 +1282,30 @@ module rosidl_parser { isComplex: false, name: "int1", type: "int32", + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { + value: 5, + }, + }, + }, }, { defaultValue: 5, isComplex: false, name: "int2", type: "int32", + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { + value: 5, + }, + }, + }, }, ], name: "action::MyAction_Goal", @@ -1289,6 +1510,15 @@ module rosidl_parser { type: "uint32", isComplex: false, defaultValue: 1, + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { + value: { usesConstant: true, name: "COLORS::GREEN" }, + }, + }, + }, }, ], }, @@ -1308,21 +1538,39 @@ module rosidl_parser { const types = parse(msgDef); expect(types).toEqual([ { - name: "JustACoupleNumbers", definitions: [ { name: "byteWithSameDefault", type: "uint8", - isComplex: false, defaultValue: 2, + isComplex: false, + annotations: { + default: { + name: "default", + namedParams: { + value: 2, + }, + type: "named-params", + }, + }, }, { name: "byteWithDifferentDefault", type: "uint8", - isComplex: false, defaultValue: 4, + isComplex: false, + annotations: { + default: { + name: "default", + namedParams: { + value: 4, + }, + type: "named-params", + }, + }, }, ], + name: "JustACoupleNumbers", }, ]); }); diff --git a/packages/omgidl-parser/src/parseIdl.ts b/packages/omgidl-parser/src/parseIdl.ts index 0ba59eb..cf8ab71 100644 --- a/packages/omgidl-parser/src/parseIdl.ts +++ b/packages/omgidl-parser/src/parseIdl.ts @@ -2,22 +2,38 @@ import { MessageDefinition } from "@foxglove/message-definition"; import { IDLNodeProcessor } from "./IDLNodeProcessor"; import { parseIdlToAST } from "./parseIdlToAST"; +import { AnnotatedMessageDefinition } from "./types"; + +/** + * Parses IDL schema to flattened AnnotatedMessageDefinitions that can be used to serialize/deserialize messages + * @param messageDefinition - idl decoded message definition string + * @returns - parsed message definition with annotations + */ +export function parseIdl(messageDefinition: string): AnnotatedMessageDefinition[] { + const rawIdlDefinitions = parseIdlToAST(messageDefinition); + + const idlProcessor = new IDLNodeProcessor(rawIdlDefinitions); + idlProcessor.resolveEnumTypes(); + idlProcessor.resolveConstants(); + idlProcessor.resolveTypeDefs(); + idlProcessor.resolveStructMemberComplexity(); + + return idlProcessor.toAnnotatedMessageDefinitions(); +} /** * Parses IDL schema to flattened MessageDefinitions that can be used to serialize/deserialize messages * @param messageDefinition - idl decoded message definition string * @returns - parsed message definition */ -export function parseIdl(messageDefinition: string): MessageDefinition[] { - const results = parseIdlToAST(messageDefinition); - - const result = results[0]!; +export function parseIdlToMessageDefinition(messageDefinition: string): MessageDefinition[] { + const rawIdlDefinitions = parseIdlToAST(messageDefinition); - const idlProcessor = new IDLNodeProcessor(result); + const idlProcessor = new IDLNodeProcessor(rawIdlDefinitions); idlProcessor.resolveEnumTypes(); idlProcessor.resolveConstants(); idlProcessor.resolveTypeDefs(); - idlProcessor.resolveComplexTypes(); + idlProcessor.resolveStructMemberComplexity(); return idlProcessor.toMessageDefinitions(); } diff --git a/packages/omgidl-parser/src/parseIdlToAST.test.ts b/packages/omgidl-parser/src/parseIdlToAST.test.ts index d1cfd48..9ce555d 100644 --- a/packages/omgidl-parser/src/parseIdlToAST.test.ts +++ b/packages/omgidl-parser/src/parseIdlToAST.test.ts @@ -9,15 +9,13 @@ describe("IDL grammar", () => { `; expect(parseIdlToAST(schema)).toEqual([ - [ - { - declarator: "struct", - definitions: [ - { isComplex: false, declarator: "struct-member", name: "input_value", type: "int32" }, - ], - name: "MyAction_Goal", - }, - ], + { + declarator: "struct", + definitions: [ + { isComplex: false, declarator: "struct-member", name: "input_value", type: "int32" }, + ], + name: "MyAction_Goal", + }, ]); }); @@ -36,47 +34,45 @@ describe("IDL grammar", () => { `; expect(parseIdlToAST(schema)).toEqual([ - [ - { - name: "idl_parser", - declarator: "module", - definitions: [ - { - name: "action", - declarator: "module", - definitions: [ - { - name: "MyAction_Goal_Constants", - declarator: "module", - definitions: [ - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "SHORT_CONSTANT", - type: "short", - value: -23, - valueText: "-23", - }, - ], - }, - { - name: "MyAction_Goal", - declarator: "struct", - definitions: [ - { - isComplex: false, - declarator: "struct-member", - name: "input_value", - type: "int32", - }, - ], - }, - ], - }, - ], - }, - ], + { + name: "idl_parser", + declarator: "module", + definitions: [ + { + name: "action", + declarator: "module", + definitions: [ + { + name: "MyAction_Goal_Constants", + declarator: "module", + definitions: [ + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "SHORT_CONSTANT", + type: "short", + value: -23, + valueText: "-23", + }, + ], + }, + { + name: "MyAction_Goal", + declarator: "struct", + definitions: [ + { + isComplex: false, + declarator: "struct-member", + name: "input_value", + type: "int32", + }, + ], + }, + ], + }, + ], + }, ]); }); it("parses all numerical types", () => { @@ -105,128 +101,126 @@ describe("IDL grammar", () => { `; expect(parseIdlToAST(schema)).toEqual([ - [ - { - name: "All_Numbers", - declarator: "struct", - definitions: [ - { - type: "unsigned short", - name: "unsigned_short_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "long", - name: "long_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "unsigned long", - name: "unsigned_long_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "long long", - name: "long_long_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "unsigned long long", - name: "unsigned_long_long_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "float", - name: "float_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "double", - name: "double_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "char", - name: "char_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "wchar", - name: "wchar_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "bool", - name: "boolean_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "octet", - name: "octet_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "int8", - name: "int8_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "uint8", - name: "uint8_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "int16", - name: "int16_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "uint16", - name: "uint16_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "int32", - name: "int32_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "uint32", - name: "uint32_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "int64", - name: "int64_value", - isComplex: false, - declarator: "struct-member", - }, - { - type: "uint64", - name: "uint64_value", - isComplex: false, - declarator: "struct-member", - }, - ], - }, - ], + { + name: "All_Numbers", + declarator: "struct", + definitions: [ + { + type: "unsigned short", + name: "unsigned_short_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "long", + name: "long_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "unsigned long", + name: "unsigned_long_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "long long", + name: "long_long_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "unsigned long long", + name: "unsigned_long_long_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "float", + name: "float_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "double", + name: "double_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "char", + name: "char_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "wchar", + name: "wchar_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "bool", + name: "boolean_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "octet", + name: "octet_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "int8", + name: "int8_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "uint8", + name: "uint8_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "int16", + name: "int16_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "uint16", + name: "uint16_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "int32", + name: "int32_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "uint32", + name: "uint32_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "int64", + name: "int64_value", + isComplex: false, + declarator: "struct-member", + }, + { + type: "uint64", + name: "uint64_value", + isComplex: false, + declarator: "struct-member", + }, + ], + }, ]); }); it("parses a module full of numeric constants", () => { @@ -245,62 +239,60 @@ module idl_parser { `, ); expect(types).toEqual([ - [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "SHORT_CONSTANT", - type: "short", - value: -23, - valueText: "-23", - }, - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "UNSIGNED_LONG_CONSTANT", - type: "unsigned long", - value: 42, - valueText: "42", - }, - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "FLOAT_CONSTANT", - type: "float", - value: 1.25, - valueText: "1.25", - }, - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "EXP_DOUBLE_CONSTANT", - type: "double", - value: 0.00125, - valueText: "1.25e-3", - }, - ], - name: "MyMessage_Constants", - }, - ], - name: "msg", - }, - ], - name: "idl_parser", - }, - ], + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "SHORT_CONSTANT", + type: "short", + value: -23, + valueText: "-23", + }, + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "UNSIGNED_LONG_CONSTANT", + type: "unsigned long", + value: 42, + valueText: "42", + }, + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "FLOAT_CONSTANT", + type: "float", + value: 1.25, + valueText: "1.25", + }, + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "EXP_DOUBLE_CONSTANT", + type: "double", + value: 0.00125, + valueText: "1.25e-3", + }, + ], + name: "MyMessage_Constants", + }, + ], + name: "msg", + }, + ], + name: "idl_parser", + }, ]); }); it("parses a module with various floating point default values", () => { @@ -341,195 +333,193 @@ module idl_parser { `, ); expect(types).toEqual([ - [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - declarator: "struct", - definitions: [ - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 19000000000 }, - }, + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + declarator: "struct", + definitions: [ + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 19000000000 }, }, - isComplex: false, - declarator: "struct-member", - name: "int_and_frac_with_positive_scientific", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 19000000000 }, - }, + isComplex: false, + declarator: "struct-member", + name: "int_and_frac_with_positive_scientific", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 19000000000 }, }, - isComplex: false, - declarator: "struct-member", - name: "int_and_frac_with_explicit_positive_scientific", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 1.1e-10 }, - }, + isComplex: false, + declarator: "struct-member", + name: "int_and_frac_with_explicit_positive_scientific", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 1.1e-10 }, }, - isComplex: false, - declarator: "struct-member", - name: "int_and_frac_with_negative_scientific", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 0.00009 }, - }, + isComplex: false, + declarator: "struct-member", + name: "int_and_frac_with_negative_scientific", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 0.00009 }, }, - isComplex: false, - declarator: "struct-member", - name: "int_and_frac", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 1 }, - }, + isComplex: false, + declarator: "struct-member", + name: "int_and_frac", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 1 }, }, - isComplex: false, - declarator: "struct-member", - name: "int_with_empty_frac", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 0.1 }, - }, + isComplex: false, + declarator: "struct-member", + name: "int_with_empty_frac", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 0.1 }, }, - isComplex: false, - declarator: "struct-member", - name: "frac_only", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 900000 }, - }, + isComplex: false, + declarator: "struct-member", + name: "frac_only", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 900000 }, }, - isComplex: false, - declarator: "struct-member", - name: "int_with_positive_scientific", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 900000 }, - }, + isComplex: false, + declarator: "struct-member", + name: "int_with_positive_scientific", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 900000 }, }, - isComplex: false, - declarator: "struct-member", - name: "int_with_explicit_positive_scientific", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 0.00009 }, - }, + isComplex: false, + declarator: "struct-member", + name: "int_with_explicit_positive_scientific", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 0.00009 }, }, - isComplex: false, - declarator: "struct-member", - name: "int_with_negative_scientific", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 8.7 }, - }, + isComplex: false, + declarator: "struct-member", + name: "int_with_negative_scientific", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 8.7 }, }, - isComplex: false, - declarator: "struct-member", - name: "fixed_int_and_frac", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 4 }, - }, + isComplex: false, + declarator: "struct-member", + name: "fixed_int_and_frac", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 4 }, }, - isComplex: false, - declarator: "struct-member", - name: "fixed_int_with_dot_only", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 0.3 }, - }, + isComplex: false, + declarator: "struct-member", + name: "fixed_int_with_dot_only", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 0.3 }, }, - isComplex: false, - declarator: "struct-member", - name: "fixed_frac_only", - type: "float", }, - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 7 }, - }, + isComplex: false, + declarator: "struct-member", + name: "fixed_frac_only", + type: "float", + }, + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 7 }, }, - isComplex: false, - declarator: "struct-member", - name: "fixed_int_only", - type: "float", }, - ], - name: "MyMessage", - }, - ], - name: "msg", - }, - ], - name: "idl_parser", - }, - ], + isComplex: false, + declarator: "struct-member", + name: "fixed_int_only", + type: "float", + }, + ], + name: "MyMessage", + }, + ], + name: "msg", + }, + ], + name: "idl_parser", + }, ]); }); it("parses a module with customTypes", () => { @@ -547,45 +537,43 @@ module idl_parser { `, ); expect(types).toEqual([ - [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - declarator: "struct", - definitions: [ - { - declarator: "struct-member", - name: "single_point", - type: "geometry::msg::Point", - }, - { - declarator: "struct-member", - arrayLength: 10, - isArray: true, - name: "points_with_length", - type: "geometry::msg::Point", - }, - { - declarator: "struct-member", - arrayUpperBound: undefined, - isArray: true, - name: "points_with_length_sequence", - type: "geometry::msg::Point", - }, - ], - name: "MyMessage", - }, - ], - name: "msg", - }, - ], - name: "idl_parser", - }, - ], + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + declarator: "struct", + definitions: [ + { + declarator: "struct-member", + name: "single_point", + type: "geometry::msg::Point", + }, + { + declarator: "struct-member", + arrayLength: 10, + isArray: true, + name: "points_with_length", + type: "geometry::msg::Point", + }, + { + declarator: "struct-member", + arrayUpperBound: undefined, + isArray: true, + name: "points_with_length_sequence", + type: "geometry::msg::Point", + }, + ], + name: "MyMessage", + }, + ], + name: "msg", + }, + ], + name: "idl_parser", + }, ]); }); it("parses a module with arbitrary annotations including default values", () => { @@ -611,122 +599,120 @@ module idl_parser { `, ); expect(types).toEqual([ - [ - { - name: "idl_parser", - declarator: "module", - definitions: [ - { - name: "msg", - declarator: "module", - definitions: [ - { - name: "MyMessage", - declarator: "struct", - annotations: { - verbatim: { - name: "verbatim", - type: "named-params", - namedParams: { - language: "comment", - text: "Documentation of MyMessage.Adjacent string literal.", - }, - }, - transfer_mode: { - name: "transfer_mode", - type: "const-param", - value: { usesConstant: true, name: "SHMEM_REF" }, + { + name: "idl_parser", + declarator: "module", + definitions: [ + { + name: "msg", + declarator: "module", + definitions: [ + { + name: "MyMessage", + declarator: "struct", + annotations: { + verbatim: { + name: "verbatim", + type: "named-params", + namedParams: { + language: "comment", + text: "Documentation of MyMessage.Adjacent string literal.", }, }, - definitions: [ - { - name: "unsigned_short_value", - isComplex: false, - declarator: "struct-member", - type: "unsigned short", - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { value: 123 }, - }, + transfer_mode: { + name: "transfer_mode", + type: "const-param", + value: { usesConstant: true, name: "SHMEM_REF" }, + }, + }, + definitions: [ + { + name: "unsigned_short_value", + isComplex: false, + declarator: "struct-member", + type: "unsigned short", + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { value: 123 }, }, }, - { - name: "long_value", - isComplex: false, - declarator: "struct-member", - type: "long", - annotations: { - key: { - name: "key", - type: "no-params", - }, - range: { - name: "range", - type: "named-params", - namedParams: { - min: -10, - max: 10, - }, + }, + { + name: "long_value", + isComplex: false, + declarator: "struct-member", + type: "long", + annotations: { + key: { + name: "key", + type: "no-params", + }, + range: { + name: "range", + type: "named-params", + namedParams: { + min: -10, + max: 10, }, }, }, - { - name: "unsigned_long_value", - isComplex: false, - declarator: "struct-member", - type: "unsigned long", - annotations: { - verbatim: { - name: "verbatim", - type: "named-params", - namedParams: { - language: "comment", - text: "", - }, - }, - arbitrary_annotation: { - name: "arbitrary_annotation", - type: "named-params", - namedParams: { - key1: "value1", - key2: true, - key3: 0.0, - key4: 10, - }, + }, + { + name: "unsigned_long_value", + isComplex: false, + declarator: "struct-member", + type: "unsigned long", + annotations: { + verbatim: { + name: "verbatim", + type: "named-params", + namedParams: { + language: "comment", + text: "", }, - key: { - name: "key", - type: "no-params", + }, + arbitrary_annotation: { + name: "arbitrary_annotation", + type: "named-params", + namedParams: { + key1: "value1", + key2: true, + key3: 0.0, + key4: 10, }, }, + key: { + name: "key", + type: "no-params", + }, }, - { - isComplex: false, - declarator: "struct-member", - name: "uint32_with_default", - type: "uint32", - annotations: { - id: { - name: "id", - type: "const-param", - value: 100, - }, - default: { - name: "default", - type: "const-param", - value: 100, - }, + }, + { + isComplex: false, + declarator: "struct-member", + name: "uint32_with_default", + type: "uint32", + annotations: { + id: { + name: "id", + type: "const-param", + value: 100, + }, + default: { + name: "default", + type: "const-param", + value: 100, }, }, - ], - }, - ], - }, - ], - }, - ], + }, + ], + }, + ], + }, + ], + }, ]); }); it("parses a module with a typedefs used in a struct", () => { @@ -746,53 +732,51 @@ module idl_parser { `, ); expect(types).toEqual([ - [ - { - name: "idl_parser", - declarator: "module", - definitions: [ - { - name: "action", - declarator: "module", - definitions: [ - { - arrayUpperBound: 10, - declarator: "typedef", - isArray: true, - isComplex: false, - name: "int32arr", - type: "int32", + { + name: "idl_parser", + declarator: "module", + definitions: [ + { + name: "action", + declarator: "module", + definitions: [ + { + arrayUpperBound: 10, + declarator: "typedef", + isArray: true, + isComplex: false, + name: "int32arr", + type: "int32", + }, + { + annotations: { + default: { name: "default", type: "named-params", namedParams: { value: 5 } }, }, - { - annotations: { - default: { name: "default", type: "named-params", namedParams: { value: 5 } }, + declarator: "typedef", + isComplex: false, + name: "shortWithDefault", + type: "short", + }, + { + name: "MyAction_Goal", + declarator: "struct", + definitions: [ + { + declarator: "struct-member", + name: "intArray", + type: "int32arr", }, - declarator: "typedef", - isComplex: false, - name: "shortWithDefault", - type: "short", - }, - { - name: "MyAction_Goal", - declarator: "struct", - definitions: [ - { - declarator: "struct-member", - name: "intArray", - type: "int32arr", - }, - { - declarator: "struct-member", - name: "short5", - type: "shortWithDefault", - }, - ], - }, - ], - }, - ], - }, - ], + { + declarator: "struct-member", + name: "short5", + type: "shortWithDefault", + }, + ], + }, + ], + }, + ], + }, ]); }); it("parses a module with an multiple enclosed structs and modules", () => { @@ -823,101 +807,99 @@ module idl_parser { `, ); expect(types).toEqual([ - [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "SHORT_CONSTANT", - type: "short", - value: -23, - valueText: "-23", - }, - ], - name: "MyAction_Goal_Constants", - }, - { - declarator: "struct", - definitions: [ - { - isComplex: false, - declarator: "struct-member", - name: "input_value", - type: "int32", - }, - ], - name: "MyAction_Goal", - }, - { - declarator: "module", - definitions: [ - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "UNSIGNED_LONG_CONSTANT", - type: "unsigned long", - value: 42, - valueText: "42", - }, - ], - name: "MyAction_Result_Constants", - }, - { - declarator: "struct", - definitions: [ - { - isComplex: false, - declarator: "struct-member", - name: "output_value", - type: "uint32", - }, - ], - name: "MyAction_Result", - }, - { - declarator: "module", - definitions: [ - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "FLOAT_CONSTANT", - type: "float", - value: 1.25, - valueText: "1.25", - }, - ], - name: "MyAction_Feedback_Constants", - }, - { - declarator: "struct", - definitions: [ - { - isComplex: false, - declarator: "struct-member", - name: "progress_value", - type: "float", - }, - ], - name: "MyAction_Feedback", - }, - ], - name: "action", - }, - ], - name: "idl_parser", - }, - ], + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "SHORT_CONSTANT", + type: "short", + value: -23, + valueText: "-23", + }, + ], + name: "MyAction_Goal_Constants", + }, + { + declarator: "struct", + definitions: [ + { + isComplex: false, + declarator: "struct-member", + name: "input_value", + type: "int32", + }, + ], + name: "MyAction_Goal", + }, + { + declarator: "module", + definitions: [ + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "UNSIGNED_LONG_CONSTANT", + type: "unsigned long", + value: 42, + valueText: "42", + }, + ], + name: "MyAction_Result_Constants", + }, + { + declarator: "struct", + definitions: [ + { + isComplex: false, + declarator: "struct-member", + name: "output_value", + type: "uint32", + }, + ], + name: "MyAction_Result", + }, + { + declarator: "module", + definitions: [ + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "FLOAT_CONSTANT", + type: "float", + value: 1.25, + valueText: "1.25", + }, + ], + name: "MyAction_Feedback_Constants", + }, + { + declarator: "struct", + definitions: [ + { + isComplex: false, + declarator: "struct-member", + name: "progress_value", + type: "float", + }, + ], + name: "MyAction_Feedback", + }, + ], + name: "action", + }, + ], + name: "idl_parser", + }, ]); }); @@ -942,47 +924,45 @@ module idl_parser { // same as above expect(types).toEqual([ - [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "SHORT_CONSTANT", - type: "short", - value: -23, - valueText: "-23", - }, - ], - name: "MyAction_Goal_Constants", - }, - { - declarator: "struct", - definitions: [ - { - isComplex: false, - declarator: "struct-member", - name: "input_value", - type: "int32", - }, - ], - name: "MyAction_Goal", - }, - ], - name: "action", - }, - ], - name: "idl_parser", - }, - ], + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "SHORT_CONSTANT", + type: "short", + value: -23, + valueText: "-23", + }, + ], + name: "MyAction_Goal_Constants", + }, + { + declarator: "struct", + definitions: [ + { + isComplex: false, + declarator: "struct-member", + name: "input_value", + type: "int32", + }, + ], + name: "MyAction_Goal", + }, + ], + name: "action", + }, + ], + name: "idl_parser", + }, ]); }); it("parses a module full of string constants", () => { @@ -1001,66 +981,64 @@ module idl_parser { `, ); expect(types).toEqual([ - [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "STRING_CONSTANT", - type: "string", - upperBound: undefined, - value: "string_value", - valueText: "string_value", - }, - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "WSTRING_CONSTANT", - type: "string", - upperBound: undefined, - value: "wstring_value_™", - valueText: "wstring_value_™", - }, - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "EMPTY_STRING_CONSTANT", - type: "string", - upperBound: undefined, - value: "", - valueText: "", - }, - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "COMBINED_STRING_CONSTANT", - type: "string", - upperBound: undefined, - value: "part1 part2 part3", - valueText: "part1 part2 part3", - }, - ], - name: "MyMessage_Constants", - }, - ], - name: "msg", - }, - ], - name: "idl_parser", - }, - ], + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "STRING_CONSTANT", + type: "string", + upperBound: undefined, + value: "string_value", + valueText: "string_value", + }, + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "WSTRING_CONSTANT", + type: "string", + upperBound: undefined, + value: "wstring_value_™", + valueText: "wstring_value_™", + }, + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "EMPTY_STRING_CONSTANT", + type: "string", + upperBound: undefined, + value: "", + valueText: "", + }, + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "COMBINED_STRING_CONSTANT", + type: "string", + upperBound: undefined, + value: "part1 part2 part3", + valueText: "part1 part2 part3", + }, + ], + name: "MyMessage_Constants", + }, + ], + name: "msg", + }, + ], + name: "idl_parser", + }, ]); }); it("parses a module of all array types", () => { @@ -1088,111 +1066,109 @@ module idl_parser { ); expect(types).toEqual([ - [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "UNSIGNED_LONG_CONSTANT", - type: "unsigned long", - value: 42, - valueText: "42", - }, - ], - name: "MyMessage_Constants", - }, - { - declarator: "struct", - definitions: [ - { - isComplex: false, - declarator: "struct-member", - name: "bounded_string_value", - type: "string", - upperBound: 5, - }, - { - isComplex: false, - declarator: "struct-member", - name: "wstring_value", - type: "string", - upperBound: undefined, - }, - { - isComplex: false, - declarator: "struct-member", - name: "bounded_wstring_value", - type: "string", - upperBound: 23, - }, - { - isComplex: false, - declarator: "struct-member", - name: "constant_bounded_wstring_value", - type: "string", - upperBound: { name: "UNSIGNED_LONG_CONSTANT", usesConstant: true }, - }, - { - arrayUpperBound: undefined, - isArray: true, - isComplex: false, - declarator: "struct-member", - name: "unbounded_short_values", - type: "short", - }, - { - arrayUpperBound: 5, - isArray: true, - isComplex: false, - declarator: "struct-member", - name: "bounded_short_values", - type: "short", - }, - { - arrayUpperBound: undefined, - isArray: true, - isComplex: false, - declarator: "struct-member", - name: "unbounded_values_of_bounded_strings", - type: "string", - upperBound: 3, - }, - { - arrayUpperBound: 4, - isArray: true, - isComplex: false, - declarator: "struct-member", - name: "bounded_values_of_bounded_strings", - type: "string", - upperBound: 3, - }, - { - arrayLength: 23, - isArray: true, - isComplex: false, - declarator: "struct-member", - name: "array_short_values", - type: "short", - }, - ], - name: "MyMessage", - }, - ], - name: "msg", - }, - ], - name: "idl_parser", - }, - ], + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "UNSIGNED_LONG_CONSTANT", + type: "unsigned long", + value: 42, + valueText: "42", + }, + ], + name: "MyMessage_Constants", + }, + { + declarator: "struct", + definitions: [ + { + isComplex: false, + declarator: "struct-member", + name: "bounded_string_value", + type: "string", + upperBound: 5, + }, + { + isComplex: false, + declarator: "struct-member", + name: "wstring_value", + type: "string", + upperBound: undefined, + }, + { + isComplex: false, + declarator: "struct-member", + name: "bounded_wstring_value", + type: "string", + upperBound: 23, + }, + { + isComplex: false, + declarator: "struct-member", + name: "constant_bounded_wstring_value", + type: "string", + upperBound: { name: "UNSIGNED_LONG_CONSTANT", usesConstant: true }, + }, + { + arrayUpperBound: undefined, + isArray: true, + isComplex: false, + declarator: "struct-member", + name: "unbounded_short_values", + type: "short", + }, + { + arrayUpperBound: 5, + isArray: true, + isComplex: false, + declarator: "struct-member", + name: "bounded_short_values", + type: "short", + }, + { + arrayUpperBound: undefined, + isArray: true, + isComplex: false, + declarator: "struct-member", + name: "unbounded_values_of_bounded_strings", + type: "string", + upperBound: 3, + }, + { + arrayUpperBound: 4, + isArray: true, + isComplex: false, + declarator: "struct-member", + name: "bounded_values_of_bounded_strings", + type: "string", + upperBound: 3, + }, + { + arrayLength: 23, + isArray: true, + isComplex: false, + declarator: "struct-member", + name: "array_short_values", + type: "short", + }, + ], + name: "MyMessage", + }, + ], + name: "msg", + }, + ], + name: "idl_parser", + }, ]); }); it("can parse comments", () => { @@ -1218,42 +1194,40 @@ module idl_parser { `; const types = parseIdlToAST(msgDef); expect(types).toEqual([ - [ - { - declarator: "module", - definitions: [ - { - declarator: "module", - definitions: [ - { - isComplex: false, - isConstant: true, - declarator: "const", - name: "tricky", - type: "string", - upperBound: undefined, - value: "/** is this a comment? */ // hopefully not", - valueText: "/** is this a comment? */ // hopefully not", - }, - ], - name: "MyAction_Goal_Constants", - }, - { - declarator: "struct", - definitions: [ - { - isComplex: false, - declarator: "struct-member", - name: "input_value", - type: "int32", - }, - ], - name: "MyAction_Goal", - }, - ], - name: "action", - }, - ], + { + declarator: "module", + definitions: [ + { + declarator: "module", + definitions: [ + { + isComplex: false, + isConstant: true, + declarator: "const", + name: "tricky", + type: "string", + upperBound: undefined, + value: "/** is this a comment? */ // hopefully not", + valueText: "/** is this a comment? */ // hopefully not", + }, + ], + name: "MyAction_Goal_Constants", + }, + { + declarator: "struct", + definitions: [ + { + isComplex: false, + declarator: "struct-member", + name: "input_value", + type: "int32", + }, + ], + name: "MyAction_Goal", + }, + ], + name: "action", + }, ]); }); it("can parse multiple forward declarations on same line with default annotation", () => { @@ -1265,32 +1239,30 @@ module idl_parser { `; const types = parseIdlToAST(msgDef); expect(types).toEqual([ - [ - { - declarator: "struct", - definitions: [ - { - annotations: { - default: { name: "default", type: "named-params", namedParams: { value: 5 } }, - }, - isComplex: false, - declarator: "struct-member", - name: "int1", - type: "int32", + { + declarator: "struct", + definitions: [ + { + annotations: { + default: { name: "default", type: "named-params", namedParams: { value: 5 } }, }, - { - annotations: { - default: { name: "default", type: "named-params", namedParams: { value: 5 } }, - }, - isComplex: false, - declarator: "struct-member", - name: "int2", - type: "int32", + isComplex: false, + declarator: "struct-member", + name: "int1", + type: "int32", + }, + { + annotations: { + default: { name: "default", type: "named-params", namedParams: { value: 5 } }, }, - ], - name: "MyAction_Goal", - }, - ], + isComplex: false, + declarator: "struct-member", + name: "int2", + type: "int32", + }, + ], + name: "MyAction_Goal", + }, ]); }); it("parses enums", () => { @@ -1303,13 +1275,11 @@ module idl_parser { `; const types = parseIdlToAST(msgDef); expect(types).toEqual([ - [ - { - declarator: "enum", - name: "COLORS", - enumerators: ["RED", "GREEN", "BLUE"], - }, - ], + { + declarator: "enum", + name: "COLORS", + enumerators: ["RED", "GREEN", "BLUE"], + }, ]); }); it("parses enums in modules", () => { @@ -1324,19 +1294,17 @@ module idl_parser { `; const types = parseIdlToAST(msgDef); expect(types).toEqual([ - [ - { - declarator: "module", - name: "Scene", - definitions: [ - { - declarator: "enum", - name: "COLORS", - enumerators: ["RED", "GREEN", "BLUE"], - }, - ], - }, - ], + { + declarator: "module", + name: "Scene", + definitions: [ + { + declarator: "enum", + name: "COLORS", + enumerators: ["RED", "GREEN", "BLUE"], + }, + ], + }, ]); }); it("parses enums used as constants", () => { @@ -1359,57 +1327,55 @@ module idl_parser { `; const types = parseIdlToAST(msgDef); expect(types).toEqual([ - [ - { - declarator: "enum", - name: "COLORS", - enumerators: ["RED", "GREEN", "BLUE"], - }, - { - declarator: "module", - name: "Scene", - definitions: [ - { - name: "DefaultColors", - declarator: "module", - definitions: [ - { - isConstant: true, - isComplex: false, - declarator: "const", - name: "red", - type: "COLORS", - value: { - name: "COLORS::RED", - usesConstant: true, - }, - valueText: "COLORS::RED", + { + declarator: "enum", + name: "COLORS", + enumerators: ["RED", "GREEN", "BLUE"], + }, + { + declarator: "module", + name: "Scene", + definitions: [ + { + name: "DefaultColors", + declarator: "module", + definitions: [ + { + isConstant: true, + isComplex: false, + declarator: "const", + name: "red", + type: "COLORS", + value: { + name: "COLORS::RED", + usesConstant: true, }, - ], - }, - { - name: "Line", - declarator: "struct", - definitions: [ - { - annotations: { - default: { - name: "default", - type: "named-params", - namedParams: { - value: { usesConstant: true, name: "COLORS::GREEN" }, - }, + valueText: "COLORS::RED", + }, + ], + }, + { + name: "Line", + declarator: "struct", + definitions: [ + { + annotations: { + default: { + name: "default", + type: "named-params", + namedParams: { + value: { usesConstant: true, name: "COLORS::GREEN" }, }, }, - declarator: "struct-member", - name: "color", - type: "COLORS", }, - ], - }, - ], - }, - ], + declarator: "struct-member", + name: "color", + type: "COLORS", + }, + ], + }, + ], + }, ]); }); it("parses multiple top level typedefs referencing each other", () => { @@ -1418,22 +1384,20 @@ module idl_parser { typedef sequence shortSeqSeq; `; expect(parseIdlToAST(msgDef)).toEqual([ - [ - { - name: "shortSeq", - declarator: "typedef", - isArray: true, - arrayUpperBound: undefined, - isComplex: false, - type: "short", - }, - { - name: "shortSeqSeq", - declarator: "typedef", - isArray: true, - type: "shortSeq", - }, - ], + { + name: "shortSeq", + declarator: "typedef", + isArray: true, + arrayUpperBound: undefined, + isComplex: false, + type: "short", + }, + { + name: "shortSeqSeq", + declarator: "typedef", + isArray: true, + type: "shortSeq", + }, ]); }); /**************** Not supported by IDL (as far as I can tell) */ diff --git a/packages/omgidl-parser/src/parseIdlToAST.ts b/packages/omgidl-parser/src/parseIdlToAST.ts index 9db296b..4b49564 100644 --- a/packages/omgidl-parser/src/parseIdlToAST.ts +++ b/packages/omgidl-parser/src/parseIdlToAST.ts @@ -3,8 +3,10 @@ import { Parser } from "nearley"; import { IDL_GRAMMAR } from "./grammar"; import { RawIdlDefinition } from "./types"; -/** Uses the IDL grammar to initialize and use a Nearley parser to read the string argument */ -export function parseIdlToAST(definition: string): RawIdlDefinition[][] { +/** Uses the IDL grammar to initialize and use a Nearley parser to read the string argument + * @returns - array of parsed IDL definitions + */ +export function parseIdlToAST(definition: string): RawIdlDefinition[] { const parser = new Parser(IDL_GRAMMAR); parser.feed(definition); parser.finish(); @@ -18,5 +20,6 @@ export function parseIdlToAST(definition: string): RawIdlDefinition[][] { if (results.length > 1) { throw new Error(`Ambiguous grammar: '${definition}'`); } - return results; + // narrowed it down to 1 array of definitions + return results[0]!; } diff --git a/packages/omgidl-parser/src/parseIdlToAST.unsupported.test.ts b/packages/omgidl-parser/src/parseIdlToAST.unsupported.test.ts index 1ee97dd..cc80492 100644 --- a/packages/omgidl-parser/src/parseIdlToAST.unsupported.test.ts +++ b/packages/omgidl-parser/src/parseIdlToAST.unsupported.test.ts @@ -62,18 +62,16 @@ describe("Unsupported IDL grammar features", () => { const short SHORT_CONSTANT = 014; `; expect(parseIdlToAST(msgDef)).toEqual([ - [ - { - name: "SHORT_CONSTANT", - declarator: "const", - isConstant: true, - isComplex: false, - type: "short", - // This should be 12, but the parser doesn't support octal literals - value: 14, - valueText: "014", - }, - ], + { + name: "SHORT_CONSTANT", + declarator: "const", + isConstant: true, + isComplex: false, + type: "short", + // This should be 12, but the parser doesn't support octal literals + value: 14, + valueText: "014", + }, ]); }); diff --git a/packages/omgidl-parser/src/types.ts b/packages/omgidl-parser/src/types.ts index d17383e..781653e 100644 --- a/packages/omgidl-parser/src/types.ts +++ b/packages/omgidl-parser/src/types.ts @@ -1,4 +1,8 @@ -import { ConstantValue, MessageDefinitionField } from "@foxglove/message-definition"; +import { + ConstantValue, + MessageDefinition, + MessageDefinitionField, +} from "@foxglove/message-definition"; type UnresolvedConstantField = Omit< MessageDefinitionField, @@ -93,3 +97,12 @@ export interface AnnotationConstParam extends BaseAnnotation { } type ResolveToConstantValue = { usesConstant: true; name: string }; + +export type AnnotatedMessageDefinitionField = MessageDefinitionField & { + annotations?: Record; +}; + +export type AnnotatedMessageDefinition = Omit & { + annotations?: Record; + definitions: AnnotatedMessageDefinitionField[]; +}; diff --git a/packages/ros2idl-parser/src/parseRos2idl.ts b/packages/ros2idl-parser/src/parseRos2idl.ts index 4d502bb..bdcccdc 100644 --- a/packages/ros2idl-parser/src/parseRos2idl.ts +++ b/packages/ros2idl-parser/src/parseRos2idl.ts @@ -1,5 +1,5 @@ import { MessageDefinition } from "@foxglove/message-definition"; -import { parseIdl } from "@foxglove/omgidl-parser"; +import { parseIdlToMessageDefinition } from "@foxglove/omgidl-parser"; /** * Parses `ros2idl` schema into flattened message definitions for serialization/deserialization. @@ -11,8 +11,7 @@ export function parseRos2idl(messageDefinition: string): MessageDefinition[] { // conform to conforming idl and just read it all in a single parse so that we don't have to call parse multiple times const idlConformedDef = messageDefinition.replaceAll(ROS2IDL_HEADER, ""); - const results = parseIdl(idlConformedDef); - + const results = parseIdlToMessageDefinition(idlConformedDef); for (const def of results) { def.name = normalizeName(def.name!); for (const field of def.definitions) {