Unnamed repository; edit this file 'description' to name the repository.
feat(languages): add Concerto modelling language support (#15472)
* feat(languages): add Concerto modelling language support
Add tree-sitter grammar and queries for the Concerto Modelling Language
(.cto files) by the Accord Project. Concerto is a schema language for
defining data models used in smart legal contracts and business networks.
Language features:
- 8 declaration types: concept, asset, participant, transaction, event,
enum, scalar, map
- 6 primitive types: String, Boolean, DateTime, Integer, Long, Double
- Decorators, validators, relationships, imports with versioning
Queries included:
- highlights.scm — full syntax highlighting
- textobjects.scm — class (type), comment, and parameter text objects
- indents.scm — auto-indentation for declaration bodies
- locals.scm — scope, definition, and reference tracking
Grammar source: https://github.com/accordproject/concerto-tree-sitter
Language spec: https://concerto.accordproject.org
| -rw-r--r-- | book/src/generated/lang-support.md | 1 | ||||
| -rw-r--r-- | languages.toml | 13 | ||||
| -rw-r--r-- | runtime/queries/concerto/highlights.scm | 235 | ||||
| -rw-r--r-- | runtime/queries/concerto/indents.scm | 21 | ||||
| -rw-r--r-- | runtime/queries/concerto/locals.scm | 88 | ||||
| -rw-r--r-- | runtime/queries/concerto/textobjects.scm | 95 |
6 files changed, 453 insertions, 0 deletions
diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 3accd33f..c82a1215 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -33,6 +33,7 @@ | codeql | ✓ | ✓ | | | | `codeql` | | comment | ✓ | | | | | | | common-lisp | ✓ | ✓ | | ✓ | ✓ | `cl-lsp` | +| concerto | ✓ | ✓ | ✓ | | | | | cpon | ✓ | | ✓ | | | | | cpp | ✓ | ✓ | ✓ | ✓ | ✓ | `clangd` | | cross-config | ✓ | ✓ | | | ✓ | `taplo`, `tombi` | diff --git a/languages.toml b/languages.toml index edbf7f6b..8d7a0ed3 100644 --- a/languages.toml +++ b/languages.toml @@ -5456,3 +5456,16 @@ comment-token = "//" [[grammar]] name = "tql" source = { git = "https://github.com/tenzir/tree-sitter-tql", rev = "d3b3b2699bc09fd0c63e2c13f15f6e474665c62e" } + +[[language]] +name = "concerto" +scope = "source.concerto" +injection-regex = "concerto" +file-types = ["cto"] +comment-tokens = "//" +block-comment-tokens = { start = "/*", end = "*/" } +indent = { tab-width = 2, unit = " " } + +[[grammar]] +name = "concerto" +source = { git = "https://github.com/accordproject/concerto-tree-sitter", rev = "77ae6b94eb0e249d1e5738c60eceed790c27563b" } diff --git a/runtime/queries/concerto/highlights.scm b/runtime/queries/concerto/highlights.scm new file mode 100644 index 00000000..a1816949 --- /dev/null +++ b/runtime/queries/concerto/highlights.scm @@ -0,0 +1,235 @@ +; Concerto Language - Syntax Highlighting Queries (Helix) +; ======================================================= +; Helix-specific capture names. For use in helix-editor/helix at +; runtime/queries/concerto/highlights.scm +; +; Precedence: later patterns override earlier ones (last match wins). + +; Keywords +; -------- + +; Declaration keywords +[ + "concept" + "asset" + "participant" + "transaction" + "event" + "enum" + "scalar" + "map" +] @keyword.storage.type + +[ + "namespace" + "import" + "from" +] @keyword.control.import + +[ + "extends" +] @keyword + +[ + "abstract" +] @keyword.storage.modifier + +[ + "identified" + "by" +] @keyword + +[ + "optional" +] @keyword.storage.modifier + +[ + "concerto" + "version" +] @keyword + +[ + "default" +] @keyword + +[ + "regex" + "range" + "length" +] @keyword + +[ + "as" +] @keyword + +; Primitive type keywords +[ + "String" + "Boolean" + "DateTime" + "Integer" + "Long" + "Double" +] @type.builtin + +(primitive_type) @type.builtin + +; Boolean literals +(boolean_literal) @constant.builtin.boolean + +; Comments +; -------- +(line_comment) @comment.line +(block_comment) @comment.block + +; Strings +; ------- +(string_literal) @string +(escape_sequence) @constant.character.escape + +; Numbers +; ------- +(signed_integer) @constant.numeric +(signed_real) @constant.numeric +(signed_number) @constant.numeric + +; Regex +; ----- +(regex_literal) @string.regexp + +; Decorators +; ---------- +(decorator + "@" @attribute + name: (identifier) @attribute) + +; Namespace and imports +; -------------------- +(namespace_path) @namespace + +(import_path) @namespace + +(uri) @string.special + +; Version +; ------- +(concerto_version + (string_literal) @string.special) + +; Type identifiers (in type position) +; ----------------------------------- +(concept_declaration + name: (type_identifier) @type) + +(asset_declaration + name: (type_identifier) @type) + +(participant_declaration + name: (type_identifier) @type) + +(transaction_declaration + name: (type_identifier) @type) + +(event_declaration + name: (type_identifier) @type) + +(enum_declaration + name: (type_identifier) @type) + +(scalar_declaration + name: (type_identifier) @type) + +(map_declaration + name: (type_identifier) @type) + +(extends_clause + (type_identifier) @type) + +; Field type references +(object_field + type: (type_identifier) @type) + +(relationship_field + type: (type_identifier) @type) + +; Map type references +(map_key_type + type: (type_identifier) @type) + +(map_value_property + type: (type_identifier) @type) + +(map_value_relationship + type: (type_identifier) @type) + +; Decorator identifier references +(decorator_identifier_ref + (type_identifier) @type) + +; Import type name +(import_single + type: (identifier) @type) + +(type_list_item + (identifier) @type) + +(aliased_type + original: (identifier) @type + alias: (identifier) @type) + +; Field/property names +; -------------------- +(string_field + name: (identifier) @variable.other.member) + +(boolean_field + name: (identifier) @variable.other.member) + +(datetime_field + name: (identifier) @variable.other.member) + +(integer_field + name: (identifier) @variable.other.member) + +(long_field + name: (identifier) @variable.other.member) + +(double_field + name: (identifier) @variable.other.member) + +(object_field + name: (identifier) @variable.other.member) + +(relationship_field + name: (identifier) @variable.other.member) + +(enum_property + name: (identifier) @variable.other.member) + +; Identified by field name +(identified_by + field: (identifier) @variable.other.member) + +; Relationship arrow +"-->" @operator + +; Property indicator +"o" @punctuation.special + +; Array indicator +(array_indicator) @punctuation.bracket + +; Wildcards in imports +"*" @operator + +; Delimiters +; ---------- +"{" @punctuation.bracket +"}" @punctuation.bracket +"(" @punctuation.bracket +")" @punctuation.bracket +"[" @punctuation.bracket +"]" @punctuation.bracket +"," @punctuation.delimiter +"." @punctuation.delimiter +"=" @operator diff --git a/runtime/queries/concerto/indents.scm b/runtime/queries/concerto/indents.scm new file mode 100644 index 00000000..a0b6158e --- /dev/null +++ b/runtime/queries/concerto/indents.scm @@ -0,0 +1,21 @@ +; Concerto Language - Indent Queries (Helix) +; ============================================ +; Helix-specific indentation rules. For use in helix-editor/helix at +; runtime/queries/concerto/indents.scm +; +; Helix uses @indent and @outdent captures, same as tree-sitter convention. +; See: https://docs.helix-editor.com/guides/indent.html + +; Indent inside declaration bodies and decorator argument lists +[ + (class_body) + (enum_body) + (map_body) + (decorator_arguments) +] @indent + +; Outdent at closing braces and parentheses +[ + "}" + ")" +] @outdent diff --git a/runtime/queries/concerto/locals.scm b/runtime/queries/concerto/locals.scm new file mode 100644 index 00000000..1dc1ee6e --- /dev/null +++ b/runtime/queries/concerto/locals.scm @@ -0,0 +1,88 @@ +; Concerto Language - Locals Queries (Helix) +; ============================================ +; Helix-specific local scope/definition/reference tracking. For use in +; helix-editor/helix at runtime/queries/concerto/locals.scm +; +; Helix uses the same @local.scope, @local.definition, and @local.reference +; capture names as tree-sitter convention. + +; Scopes +; ------ + +; Each declaration body creates a new scope +(concept_declaration) @local.scope +(asset_declaration) @local.scope +(participant_declaration) @local.scope +(transaction_declaration) @local.scope +(event_declaration) @local.scope +(enum_declaration) @local.scope +(map_declaration) @local.scope + +; Definitions +; ----------- + +; Type declarations define types +(concept_declaration + name: (type_identifier) @local.definition.type) + +(asset_declaration + name: (type_identifier) @local.definition.type) + +(participant_declaration + name: (type_identifier) @local.definition.type) + +(transaction_declaration + name: (type_identifier) @local.definition.type) + +(event_declaration + name: (type_identifier) @local.definition.type) + +(enum_declaration + name: (type_identifier) @local.definition.type) + +(scalar_declaration + name: (type_identifier) @local.definition.type) + +(map_declaration + name: (type_identifier) @local.definition.type) + +; Property declarations define properties +(string_field + name: (identifier) @local.definition.variable.other.member) + +(boolean_field + name: (identifier) @local.definition.variable.other.member) + +(datetime_field + name: (identifier) @local.definition.variable.other.member) + +(integer_field + name: (identifier) @local.definition.variable.other.member) + +(long_field + name: (identifier) @local.definition.variable.other.member) + +(double_field + name: (identifier) @local.definition.variable.other.member) + +(object_field + name: (identifier) @local.definition.variable.other.member) + +(relationship_field + name: (identifier) @local.definition.variable.other.member) + +(enum_property + name: (identifier) @local.definition.variable.other.member) + +; References +; ---------- + +; Type references +(extends_clause + (type_identifier) @local.reference) + +(object_field + type: (type_identifier) @local.reference) + +(relationship_field + type: (type_identifier) @local.reference) diff --git a/runtime/queries/concerto/textobjects.scm b/runtime/queries/concerto/textobjects.scm new file mode 100644 index 00000000..55b515a1 --- /dev/null +++ b/runtime/queries/concerto/textobjects.scm @@ -0,0 +1,95 @@ +; Concerto Language - Text Object Queries (Helix) +; ================================================= +; Helix-specific text objects. For use in helix-editor/helix at +; runtime/queries/concerto/textobjects.scm +; +; Helix uses @<object>.around / @<object>.inside suffixes. +; See: https://docs.helix-editor.com/guides/textobject.html + +; --------------------------------------------------------------------------- +; Classes / declarations +; --------------------------------------------------------------------------- +; mac / mic — select around/inside class +; ]c / [c — jump to next/prev class boundary + +(concept_declaration + (class_body + . + "{" + _+ @class.inside + "}")) @class.around + +(asset_declaration + (class_body + . + "{" + _+ @class.inside + "}")) @class.around + +(participant_declaration + (class_body + . + "{" + _+ @class.inside + "}")) @class.around + +(transaction_declaration + (class_body + . + "{" + _+ @class.inside + "}")) @class.around + +(event_declaration + (class_body + . + "{" + _+ @class.inside + "}")) @class.around + +(enum_declaration + (enum_body + . + "{" + _+ @class.inside + "}")) @class.around + +(map_declaration + (map_body + . + "{" + _+ @class.inside + "}")) @class.around + +; Scalar declarations have no body braces — around only +(scalar_declaration) @class.around + +; --------------------------------------------------------------------------- +; Comments +; --------------------------------------------------------------------------- +; ]C / [C — jump to next/prev comment +; maC / miC — select around/inside comment + +(line_comment) @comment.inside +(block_comment) @comment.inside + +(line_comment) @comment.around +(block_comment) @comment.around + +; --------------------------------------------------------------------------- +; Parameters — fields, enum values, map entries +; --------------------------------------------------------------------------- +; ]a / [a — jump to next/prev parameter +; maa / mia — select around/inside parameter + +(string_field) @parameter.inside +(boolean_field) @parameter.inside +(datetime_field) @parameter.inside +(integer_field) @parameter.inside +(long_field) @parameter.inside +(double_field) @parameter.inside +(object_field) @parameter.inside +(relationship_field) @parameter.inside +(enum_property) @parameter.inside +(map_key_type) @parameter.inside +(map_value_type) @parameter.inside |