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
Jamie Shorten 5 weeks ago
parent 954c67c · commit b5cb6b9
-rw-r--r--book/src/generated/lang-support.md1
-rw-r--r--languages.toml13
-rw-r--r--runtime/queries/concerto/highlights.scm235
-rw-r--r--runtime/queries/concerto/indents.scm21
-rw-r--r--runtime/queries/concerto/locals.scm88
-rw-r--r--runtime/queries/concerto/textobjects.scm95
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