Repository: common-workflow-language/schema_salad (language: python)

Issue:
Imported array is flattened in the parent array rather than replacing `$import` node
The [spec](https://www.commonwl.org/v1.2/SchemaSalad.html#Import) says:
> Once loaded and processed, the `$import` node is replaced in the document structure by the object or array yielded from the import operation.

However, when the loaded object is an array, it is flattened in the parent array rather than replacing `$import` node.

# How to reproduce

parent.json:
```json
{
    "form": [
        "bar",
        {
            "$import": "import.json"
        }
    ]
}
```

import.json
```json
["hello", "world"]
```

```console
$ schema-salad-tool --print-pre parent.json
```

# Expected behavior
The `$import` node is replaced by an array as follows:
```console
$ schema-salad-tool --print-pre parent.json
{
    "form": [
        "bar",
        [
            "hello",
            "world"
        ]
    ],
    "name": "file:///workspaces/schema_salad/parent.json"
}
```

# Actual behavior
Elements in the array in the `$import`ed document are flattened in the parent array as follows:

```console
$ schema-salad-tool --print-pre parent.json
{
    "form": [
        "bar",
        "hello",
        "world"
    ],
    "name": "file:///workspaces/schema_salad/parent.json"
}
```

# Versions

```console
$ schema-salad-tool --version
/home/vscode/.local/bin/schema-salad-tool Current version: 8.2.20211116214159
```

Note that this undocumented behavior is already used in [metaschema](https://github.com/common-workflow-language/schema_salad/blob/e90a5574519c29b6887a962ec4d408ccb00eb526/schema_salad/metaschema/metaschema.yml#L17).



Discussion / hints:
You are right.  This should be documented.  Possibly we could introduce a new operation that has explicit insert/merge behavior and make import behave consistently.

Fix patch:
diff --git a/schema_salad/metaschema/import_include.md b/schema_salad/metaschema/import_include.md
index 84397f7a..980240e9 100644
--- a/schema_salad/metaschema/import_include.md
+++ b/schema_salad/metaschema/import_include.md
@@ -16,8 +16,9 @@ document must be the URI used to retrieve the imported document.  If the
 `$import` URI includes a document fragment, the fragment must be excluded
 from the base URI used to preprocess the imported document.
 
-Once loaded and processed, the `$import` node is replaced in the document
-structure by the object or array yielded from the import operation.
+If the `$import` node is in an array and the import operation yields an array,
+it is flattened to the parent array. Otherwise the `$import` node is replaced
+in the document structure by the object or array yielded from the import operation.
 
 URIs may reference document fragments which refer to specific an object in
 the target document.  This indicates that the `$import` node must be
@@ -26,7 +27,7 @@ replaced by only the object with the appropriate fragment identifier.
 It is a fatal error if an import directive refers to an external resource
 or resource fragment which does not exist or is not accessible.
 
-### Import example
+### Import example: replacing the `$import` node
 
 import.json:
 ```
@@ -60,6 +61,38 @@ This becomes:
 }
 ```
 
+### Import example: flattening the `$import`ed array
+
+import.json:
+```
+[ "hello", "world" ]
+```
+
+parent.json:
+```
+{
+  "form": [
+    "bar",
+    {
+      "$import": "import.json"
+    }
+  ]
+}
+
+```
+
+This becomes:
+
+```
+{
+  "form": [
+    "bar",
+    "hello",
+    "world"
+  ]
+}
+```
+
 ## Include
 
 During preprocessing traversal, an implementation must resolve `$include`


Test patch:
diff --git a/schema_salad/tests/metaschema-pre.yml b/schema_salad/tests/metaschema-pre.yml
index 9b2d2deb..e4861773 100644
--- a/schema_salad/tests/metaschema-pre.yml
+++ b/schema_salad/tests/metaschema-pre.yml
@@ -1,5 +1,6 @@
 [
     {
+        "name": "https://w3id.org/cwl/salad#Semantic_Annotations_for_Linked_Avro_Data",
         "type": "documentation",
         "doc": [
             "# Semantic Annotations for Linked Avro Data (SALAD)\n\nAuthor:\n\n* Peter Amstutz <pamstutz@veritasgenetics.com>, Veritas Genetics\n\nContributors:\n\n* The developers of Apache Avro\n* The developers of JSON-LD\n* Neboj\u0161a Tijani\u0107 <nebojsa.tijanic@sbgenomics.com>, Seven Bridges Genomics\n\n# Abstract\n\nSalad is a schema language for describing structured linked data documents\nin JSON or YAML documents.  A Salad schema provides rules for\npreprocessing, structural validation, and link checking for documents\ndescribed by a Salad schema.  Salad builds on JSON-LD and the Apache Avro\ndata serialization system, and extends Avro with features for rich data\nmodeling such as inheritance, template specialization, object identifiers,\nand object references.  Salad was developed to provide a bridge between the\nrecord oriented data modeling supported by Apache Avro and the Semantic\nWeb.\n\n# Status of This Document\n\nThis document is the product of the [Common Workflow Language working\ngroup](https://groups.google.com/forum/#!forum/common-workflow-language).  The\nlatest version of this document is available in the \"schema_salad\" repository at\n\nhttps://github.com/common-workflow-language/schema_salad\n\nThe products of the CWL working group (including this document) are made available\nunder the terms of the Apache License, version 2.0.\n\n<!--ToC-->\n\n# Introduction\n\nThe JSON data model is an extremely popular way to represent structured\ndata.  It is attractive because of its relative simplicity and is a\nnatural fit with the standard types of many programming languages.\nHowever, this simplicity means that basic JSON lacks expressive features\nuseful for working with complex data structures and document formats, such\nas schemas, object references, and namespaces.\n\nJSON-LD is a W3C standard providing a way to describe how to interpret a\nJSON document as Linked Data by means of a \"context\".  JSON-LD provides a\npowerful solution for representing object references and namespaces in JSON\nbased on standard web URIs, but is not itself a schema language.  Without a\nschema providing a well defined structure, it is difficult to process an\narbitrary JSON-LD document as idiomatic JSON because there are many ways to\nexpress the same data that are logically equivalent but structurally\ndistinct.\n\nSeveral schema languages exist for describing and validating JSON data,\nsuch as the Apache Avro data serialization system, however none understand\nlinked data.  As a result, to fully take advantage of JSON-LD to build the\nnext generation of linked data applications, one must maintain separate\nJSON schema, JSON-LD context, RDF schema, and human documentation, despite\nsignificant overlap of content and obvious need for these documents to stay\nsynchronized.\n\nSchema Salad is designed to address this gap.  It provides a schema\nlanguage and processing rules for describing structured JSON content\npermitting URI resolution and strict document validation.  The schema\nlanguage supports linked data through annotations that describe the linked\ndata interpretation of the content, enables generation of JSON-LD context\nand RDF schema, and production of RDF triples by applying the JSON-LD\ncontext.  The schema language also provides for robust support of inline\ndocumentation.\n\n## Introduction to v1.1\n\nThis is the third version of of the Schema Salad specification.  It is\ndeveloped concurrently with v1.1 of the Common Workflow Language for use in\nspecifying the Common Workflow Language, however Schema Salad is intended to be\nuseful to a broader audience.  Compared to the v1.0 schema salad\nspecification, the following changes have been made:\n\n* Support for `default` values on record fields to specify default values\n* Add subscoped fields (fields which introduce a new inner scope for identifiers)\n* Add the *inVocab* flag (default true) to indicate if a type is added to the vocabulary of well known terms or must be prefixed\n* Add *secondaryFilesDSL* micro DSL (domain specific language) to convert text strings to a secondaryFiles record type used in CWL\n* The `$mixin` feature has been removed from the specification, as it\n  is poorly documented, not included in conformance testing,\n  and not widely supported.\n\n## References to Other Specifications\n\n**Javascript Object Notation (JSON)**: http://json.org\n\n**JSON Linked Data (JSON-LD)**: http://json-ld.org\n\n**YAML**: https://yaml.org/spec/1.2/spec.html\n\n**Avro**: https://avro.apache.org/docs/current/spec.html\n\n**Uniform Resource Identifier (URI) Generic Syntax**: https://tools.ietf.org/html/rfc3986)\n\n**Resource Description Framework (RDF)**: http://www.w3.org/RDF/\n\n**UTF-8**: https://www.ietf.org/rfc/rfc2279.txt)\n\n## Scope\n\nThis document describes the syntax, data model, algorithms, and schema\nlanguage for working with Salad documents.  It is not intended to document\na specific implementation of Salad, however it may serve as a reference for\nthe behavior of conforming implementations.\n\n## Terminology\n\nThe terminology used to describe Salad documents is defined in the Concepts\nsection of the specification. The terms defined in the following list are\nused in building those definitions and in describing the actions of an\nSalad implementation:\n\n**may**: Conforming Salad documents and Salad implementations are permitted but\nnot required to be interpreted as described.\n\n**must**: Conforming Salad documents and Salad implementations are required\nto be interpreted as described; otherwise they are in error.\n\n**error**: A violation of the rules of this specification; results are\nundefined. Conforming implementations may detect and report an error and may\nrecover from it.\n\n**fatal error**: A violation of the rules of this specification; results\nare undefined. Conforming implementations must not continue to process the\ndocument and may report an error.\n\n**at user option**: Conforming software may or must (depending on the modal verb in\nthe sentence) behave as described; if it does, it must provide users a means to\nenable or disable the behavior described.\n\n# Document model\n\n## Data concepts\n\nAn **object** is a data structure equivalent to the \"object\" type in JSON,\nconsisting of a unordered set of name/value pairs (referred to here as\n**fields**) and where the name is a string and the value is a string, number,\nboolean, array, or object.\n\nA **document** is a file containing a serialized object, or an array of\nobjects.\n\nA **document type** is a class of files that share a common structure and\nsemantics.\n\nA **document schema** is a formal description of the grammar of a document type.\n\nA **base URI** is a context-dependent URI used to resolve relative references.\n\nAn **identifier** is a URI that designates a single document or single\nobject within a document.\n\nA **vocabulary** is the set of symbolic field names and enumerated symbols defined\nby a document schema, where each term maps to absolute URI.\n\n## Syntax\n\nConforming Salad v1.1 documents are serialized and loaded using a\nsubset of YAML 1.2 syntax and UTF-8 text encoding.  Salad documents\nare written using the [JSON-compatible subset of YAML described in\nsection 10.2](https://yaml.org/spec/1.2/spec.html#id2803231).  The\nfollowing features of YAML must not be used in conforming Salad\ndocuments:\n\n* Use of explicit node tags with leading `!` or `!!`\n* Use of anchors with leading `&` and aliases with leading `*`\n* %YAML directives\n* %TAG directives\n\nIt is a fatal error if the document is not valid YAML.\n\nA Salad document must consist only of either a single root object or an\narray of objects.\n\n## Document context\n\n### Implied context\n\nThe implicit context consists of the vocabulary defined by the schema and\nthe base URI.  By default, the base URI must be the URI that was used to\nload the document.  It may be overridden by an explicit context.\n\n### Explicit context\n\nIf a document consists of a root object, this object may contain the\nfields `$base`, `$namespaces`, `$schemas`, and `$graph`:\n\n  * `$base`: Must be a string.  Set the base URI for the document used to\n    resolve relative references.\n\n  * `$namespaces`: Must be an object with strings as values.  The keys of\n    the object are namespace prefixes used in the document; the values of\n    the object are the prefix expansions.\n\n  * `$schemas`: Must be an array of strings.  This field may list URI\n    references to documents in RDF-XML format which will be queried for RDF\n    schema data.  The subjects and predicates described by the RDF schema\n    may provide additional semantic context for the document, and may be\n    used for validation of prefixed extension fields found in the document.\n\nOther directives beginning with `$` must be ignored.\n\n## Document graph\n\nIf a document consists of a single root object, this object may contain the\nfield `$graph`.  This field must be an array of objects.  If present, this\nfield holds the primary content of the document.  A document that consists\nof array of objects at the root is an implicit graph.\n\n## Document metadata\n\nIf a document consists of a single root object, metadata about the\ndocument, such as authorship, may be declared in the root object.\n\n## Document schema\n\nDocument preprocessing, link validation and schema validation require a\ndocument schema.  A schema may consist of:\n\n  * At least one record definition object which defines valid fields that\n  make up a record type.  Record field definitions include the valid types\n  that may be assigned to each field and annotations to indicate fields\n  that represent identifiers and links, described below in \"Semantic\n  Annotations\".\n\n  * Any number of enumerated type objects which define a set of finite set of symbols that are\n  valid value of the type.\n\n  * Any number of documentation objects which allow in-line documentation of the schema.\n\nThe schema for defining a salad schema (the metaschema) is described in\ndetail in the [Schema](#Schema) section.\n\n## Record field annotations\n\nIn a document schema, record field definitions may include the field\n`jsonldPredicate`, which may be either a string or object.  Implementations\nmust use the following document preprocessing of fields by the following\nrules:\n\n  * If the value of `jsonldPredicate` is `@id`, the field is an identifier\n  field.\n\n  * If the value of `jsonldPredicate` is an object, and that\n  object contains the field `_type` with the value `@id`, the field is a\n  link field subject to [link validation](#Link_validation).\n\n  * If the value of `jsonldPredicate` is an object which contains the\n  field `_type` with the value `@vocab`, the field value is subject to\n  [vocabulary resolution](#Vocabulary_resolution).\n\n## Document traversal\n\nTo perform document document preprocessing, link validation and schema\nvalidation, the document must be traversed starting from the fields or\narray items of the root object or array and recursively visiting each child\nitem which contains an object or arrays.\n\n## Short names\n\nThe \"short name\" of an fully qualified identifier is the portion of\nthe identifier following the final slash `/` of either the fragment\nidentifier following `#` or the path portion, if there is no fragment.\nSome examples:\n\n* the short name of `http://example.com/foo` is `foo`\n* the short name of `http://example.com/#bar` is `bar`\n* the short name of `http://example.com/foo/bar` is `bar`\n* the short name of `http://example.com/foo#bar` is `bar`\n* the short name of `http://example.com/#foo/bar` is `bar`\n* the short name of `http://example.com/foo#bar/baz` is `baz`\n\n## Inheritance and specialization\n\nA record definition may inherit from one or more record definitions\nwith the `extends` field.  This copies the fields defined in the\nparent record(s) as the base for the new record.  A record definition\nmay `specialize` type declarations of the fields inherited from the\nbase record.  For each field inherited from the base record, any\ninstance of the type in `specializeFrom` is replaced with the type in\n`specializeTo`.  The type in `specializeTo` should extend from the\ntype in `specializeFrom`.\n\nA record definition may be `abstract`.  This means the record\ndefinition is not used for validation on its own, but may be extended\nby other definitions.  If an abstract type appears in a field\ndefinition, it is logically replaced with a union of all concrete\nsubtypes of the abstract type.  In other words, the field value does\nnot validate as the abstract type, but must validate as some concrete\ntype that inherits from the abstract type.\n\n# Document preprocessing\n\nAfter processing the explicit context (if any), document preprocessing\nbegins.  Starting from the document root, object fields values or array\nitems which contain objects or arrays are recursively traversed\ndepth-first.  For each visited object, field names, identifier fields, link\nfields, vocabulary fields, and `$import` and `$include` directives must be\nprocessed as described in this section.  The order of traversal of child\nnodes within a parent node is undefined.\n",
@@ -31,7 +32,7 @@
             "```\n\nThis becomes:\n\n```\n",
             "    {\n      \"form\": {\n        \"things\": [\n          {\n            \"voc\": \"red\",\n          },\n          {\n            \"voc\": \"red\",\n          },\n          {\n            \"voc\": \"http://example.com/acid#blue\",\n          }\n        ]\n      }\n    }\n",
             "```\n",
-            "## Import\n\nDuring preprocessing traversal, an implementation must resolve `$import`\ndirectives.  An `$import` directive is an object consisting of exactly one\nfield `$import` specifying resource by URI string.  It is an error if there\nare additional fields in the `$import` object, such additional fields must\nbe ignored.\n\nThe URI string must be resolved to an absolute URI using the link\nresolution rules described previously.  Implementations must support\nloading from `file`, `http` and `https` resources.  The URI referenced by\n`$import` must be loaded and recursively preprocessed as a Salad document.\nThe external imported document does not inherit the context of the\nimporting document, and the default base URI for processing the imported\ndocument must be the URI used to retrieve the imported document.  If the\n`$import` URI includes a document fragment, the fragment must be excluded\nfrom the base URI used to preprocess the imported document.\n\nOnce loaded and processed, the `$import` node is replaced in the document\nstructure by the object or array yielded from the import operation.\n\nURIs may reference document fragments which refer to specific an object in\nthe target document.  This indicates that the `$import` node must be\nreplaced by only the object with the appropriate fragment identifier.\n\nIt is a fatal error if an import directive refers to an external resource\nor resource fragment which does not exist or is not accessible.\n\n### Import example\n\nimport.json:\n```\n{\n  \"hello\": \"world\"\n}\n\n```\n\nparent.json:\n```\n{\n  \"form\": {\n    \"bar\": {\n      \"$import\": \"import.json\"\n      }\n  }\n}\n\n```\n\nThis becomes:\n\n```\n{\n  \"form\": {\n    \"bar\": {\n      \"hello\": \"world\"\n    }\n  }\n}\n```\n\n## Include\n\nDuring preprocessing traversal, an implementation must resolve `$include`\ndirectives.  An `$include` directive is an object consisting of exactly one\nfield `$include` specifying a URI string.  It is an error if there are\nadditional fields in the `$include` object, such additional fields must be\nignored.\n\nThe URI string must be resolved to an absolute URI using the link\nresolution rules described previously.  The URI referenced by `$include` must\nbe loaded as a text data.  Implementations must support loading from\n`file`, `http` and `https` resources.  Implementations may transcode the\ncharacter encoding of the text data to match that of the parent document,\nbut must not interpret or parse the text document in any other way.\n\nOnce loaded, the `$include` node is replaced in the document structure by a\nstring containing the text data loaded from the resource.\n\nIt is a fatal error if an import directive refers to an external resource\nwhich does not exist or is not accessible.\n\n### Include example\n\nparent.json:\n```\n{\n  \"form\": {\n    \"bar\": {\n      \"$include\": \"include.txt\"\n      }\n  }\n}\n\n```\n\ninclude.txt:\n```\nhello world\n\n```\n\nThis becomes:\n\n```\n{\n  \"form\": {\n    \"bar\": \"hello world\"\n  }\n}\n```\n",
+            "## Import\n\nDuring preprocessing traversal, an implementation must resolve `$import`\ndirectives.  An `$import` directive is an object consisting of exactly one\nfield `$import` specifying resource by URI string.  It is an error if there\nare additional fields in the `$import` object, such additional fields must\nbe ignored.\n\nThe URI string must be resolved to an absolute URI using the link\nresolution rules described previously.  Implementations must support\nloading from `file`, `http` and `https` resources.  The URI referenced by\n`$import` must be loaded and recursively preprocessed as a Salad document.\nThe external imported document does not inherit the context of the\nimporting document, and the default base URI for processing the imported\ndocument must be the URI used to retrieve the imported document.  If the\n`$import` URI includes a document fragment, the fragment must be excluded\nfrom the base URI used to preprocess the imported document.\n\nIf the `$import` node is in an array and the import operation yields an array,\nit is flattened to the parent array. Otherwise the `$import` node is replaced\nin the document structure by the object or array yielded from the import operation.\n\nURIs may reference document fragments which refer to specific an object in\nthe target document.  This indicates that the `$import` node must be\nreplaced by only the object with the appropriate fragment identifier.\n\nIt is a fatal error if an import directive refers to an external resource\nor resource fragment which does not exist or is not accessible.\n\n### Import example: replacing the `$import` node\n\nimport.json:\n```\n{\n  \"hello\": \"world\"\n}\n\n```\n\nparent.json:\n```\n{\n  \"form\": {\n    \"bar\": {\n      \"$import\": \"import.json\"\n      }\n  }\n}\n\n```\n\nThis becomes:\n\n```\n{\n  \"form\": {\n    \"bar\": {\n      \"hello\": \"world\"\n    }\n  }\n}\n```\n\n### Import example: flattening the `$import`ed array\n\nimport.json:\n```\n[ \"hello\", \"world\" ]\n```\n\nparent.json:\n```\n{\n  \"form\": [\n    \"bar\",\n    {\n      \"$import\": \"import.json\"\n    }\n  ]\n}\n\n```\n\nThis becomes:\n\n```\n{\n  \"form\": [\n    \"bar\",\n    \"hello\",\n    \"world\"\n  ]\n}\n```\n\n## Include\n\nDuring preprocessing traversal, an implementation must resolve `$include`\ndirectives.  An `$include` directive is an object consisting of exactly one\nfield `$include` specifying a URI string.  It is an error if there are\nadditional fields in the `$include` object, such additional fields must be\nignored.\n\nThe URI string must be resolved to an absolute URI using the link\nresolution rules described previously.  The URI referenced by `$include` must\nbe loaded as a text data.  Implementations must support loading from\n`file`, `http` and `https` resources.  Implementations may transcode the\ncharacter encoding of the text data to match that of the parent document,\nbut must not interpret or parse the text document in any other way.\n\nOnce loaded, the `$include` node is replaced in the document structure by a\nstring containing the text data loaded from the resource.\n\nIt is a fatal error if an import directive refers to an external resource\nwhich does not exist or is not accessible.\n\n### Include example\n\nparent.json:\n```\n{\n  \"form\": {\n    \"bar\": {\n      \"$include\": \"include.txt\"\n      }\n  }\n}\n\n```\n\ninclude.txt:\n```\nhello world\n\n```\n\nThis becomes:\n\n```\n{\n  \"form\": {\n    \"bar\": \"hello world\"\n  }\n}\n```\n",
             "## Identifier maps\n\nThe schema may designate certain fields as having a `mapSubject`.  If the\nvalue of the field is a JSON object, it must be transformed into an array of\nJSON objects.  Each key-value pair from the source JSON object is a list\nitem, each list item must be a JSON object, and the value of the key is\nassigned to the field specified by `mapSubject`.\n\nFields which have `mapSubject` specified may also supply a `mapPredicate`.\nIf the value of a map item is not a JSON object, the item is transformed to a\nJSON object with the key assigned to the field specified by `mapSubject` and\nthe value assigned to the field specified by `mapPredicate`.\n\n### Identifier map example\n\nGiven the following schema:\n\n```\n",
             "{\n  \"$graph\": [{\n    \"name\": \"MappedType\",\n    \"type\": \"record\",\n    \"documentRoot\": true,\n    \"fields\": [{\n      \"name\": \"mapped\",\n      \"type\": {\n        \"type\": \"array\",\n        \"items\": \"ExampleRecord\"\n      },\n      \"jsonldPredicate\": {\n        \"mapSubject\": \"key\",\n        \"mapPredicate\": \"value\"\n      }\n    }],\n  },\n  {\n    \"name\": \"ExampleRecord\",\n    \"type\": \"record\",\n    \"fields\": [{\n      \"name\": \"key\",\n      \"type\": \"string\"\n      }, {\n      \"name\": \"value\",\n      \"type\": \"string\"\n      }\n    ]\n  }]\n}\n",
             "```\n\nProcess the following example:\n\n```\n",
@@ -53,47 +54,56 @@
             "```\n\nThis becomes:\n\n```\n",
             "[\n    {\n        \"secondaryFiles\": {\n          \"pattern\": \".bai\",\n          \"required\": null\n    },\n    {\n        \"secondaryFiles\": {\n          \"pattern\": \".bai\",\n          \"required\": false\n    },\n    {\n        \"secondaryFiles\": {\n          \"pattern\": \".bai?\"\n    },\n    {\n        \"secondaryFiles\": {\n          \"pattern\": \".bai?\",\n          \"required\": true\n    },\n]\n",
             "```\n"
-        ],
-        "name": "https://w3id.org/cwl/salad#Semantic_Annotations_for_Linked_Avro_Data"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#Link_Validation",
         "type": "documentation",
-        "doc": "# Link validation\n\nOnce a document has been preprocessed, an implementation may validate\nlinks.  The link validation traversal may visit fields which the schema\ndesignates as link fields and check that each URI references an existing\nobject in the current document, an imported document, file system, or\nnetwork resource.  Failure to validate links may be a fatal error.  Link\nvalidation behavior for individual fields may be modified by `identity` and\n`noLinkCheck` in the `jsonldPredicate` section of the field schema.\n",
-        "name": "https://w3id.org/cwl/salad#Link_Validation"
+        "doc": "# Link validation\n\nOnce a document has been preprocessed, an implementation may validate\nlinks.  The link validation traversal may visit fields which the schema\ndesignates as link fields and check that each URI references an existing\nobject in the current document, an imported document, file system, or\nnetwork resource.  Failure to validate links may be a fatal error.  Link\nvalidation behavior for individual fields may be modified by `identity` and\n`noLinkCheck` in the `jsonldPredicate` section of the field schema.\n"
     },
     {
+        "name": "https://w3id.org/cwl/salad#Schema_Validation",
         "type": "documentation",
-        "doc": "# Validating a document against a schema\n\nTo validate a document against the schema, first [apply\npreprocessing](#Document_preprocessing), then, use the following\nalgorithm.\n\n1. The document root must be an object or a list.  If the document root is an\n   object containing the field `$graph` (which must be a list of\n   objects), then validation applies to each object in the list.\n2. For each object, attempt to validate as one of the record types\n   flagged with `documentRoot: true`.\n3. To validate a record, go through `fields` and recursively\n   validate each field of the object.\n4. For fields with a list of types (type union), go through each\n   type in the list and recursively validate the type.  For the\n   field to be valid, at least one type in the union must be valid.\n5. Missing fields are considered `null`.  To validate, the allowed types\n   for the field must include `null`\n6. Primitive types are null, boolean, int, long, float, double,\n   string.  To validate, the value in the document must have one\n   of these type.  For numerics, the value appearing in the\n   document must fit into the specified type.\n7. To validate an array, the value in the document must be a list,\n   and each item in the list must recursively validate as a type\n   in `items`.\n8. To validate an enum, the value in the document be a string, and\n   the value must be equal to the short name of one of the values\n   listed in `symbols`.\n9. As a special case, a field with the `Expression` type validates string values\n  which contain a CWL parameter reference or expression in the form\n  `$(...)` or `${...}`\n",
-        "name": "https://w3id.org/cwl/salad#Schema_Validation"
+        "doc": "# Validating a document against a schema\n\nTo validate a document against the schema, first [apply\npreprocessing](#Document_preprocessing), then, use the following\nalgorithm.\n\n1. The document root must be an object or a list.  If the document root is an\n   object containing the field `$graph` (which must be a list of\n   objects), then validation applies to each object in the list.\n2. For each object, attempt to validate as one of the record types\n   flagged with `documentRoot: true`.\n3. To validate a record, go through `fields` and recursively\n   validate each field of the object.\n4. For fields with a list of types (type union), go through each\n   type in the list and recursively validate the type.  For the\n   field to be valid, at least one type in the union must be valid.\n5. Missing fields are considered `null`.  To validate, the allowed types\n   for the field must include `null`\n6. Primitive types are null, boolean, int, long, float, double,\n   string.  To validate, the value in the document must have one\n   of these type.  For numerics, the value appearing in the\n   document must fit into the specified type.\n7. To validate an array, the value in the document must be a list,\n   and each item in the list must recursively validate as a type\n   in `items`.\n8. To validate an enum, the value in the document be a string, and\n   the value must be equal to the short name of one of the values\n   listed in `symbols`.\n9. As a special case, a field with the `Expression` type validates string values\n  which contain a CWL parameter reference or expression in the form\n  `$(...)` or `${...}`\n"
     },
     {
+        "name": "https://w3id.org/cwl/salad#Schema",
         "type": "documentation",
-        "doc": "# Schema\n",
-        "name": "https://w3id.org/cwl/salad#Schema"
+        "doc": "# Schema\n"
     },
     {
+        "name": "https://w3id.org/cwl/salad#Documented",
         "type": "record",
         "abstract": true,
-        "name": "https://w3id.org/cwl/salad#Documented",
+        "docParent": "https://w3id.org/cwl/salad#Schema",
         "fields": [
             {
+                "name": "https://w3id.org/cwl/salad#Documented/doc",
                 "type": [
                     "null",
                     "string",
                     {
-                        "items": "string",
-                        "type": "array"
+                        "type": "array",
+                        "items": "string"
                     }
                 ],
                 "doc": "A documentation string for this object, or an array of strings which should be concatenated.",
-                "name": "https://w3id.org/cwl/salad#Documented/doc",
                 "jsonldPredicate": "rdfs:comment"
             }
-        ],
-        "docParent": "https://w3id.org/cwl/salad#Schema"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#PrimitiveType",
         "type": "enum",
+        "symbols": [
+            "https://w3id.org/cwl/salad#null",
+            "http://www.w3.org/2001/XMLSchema#boolean",
+            "http://www.w3.org/2001/XMLSchema#int",
+            "http://www.w3.org/2001/XMLSchema#long",
+            "http://www.w3.org/2001/XMLSchema#float",
+            "http://www.w3.org/2001/XMLSchema#double",
+            "http://www.w3.org/2001/XMLSchema#string"
+        ],
         "doc": [
             "Salad data types are based on Avro schema declarations.  Refer to the\n[Avro schema declaration documentation](https://avro.apache.org/docs/current/spec.html#schemas) for\ndetailed information.\n",
             "null: no value",
@@ -103,37 +113,31 @@
             "float: single precision (32-bit) IEEE 754 floating-point number",
             "double: double precision (64-bit) IEEE 754 floating-point number",
             "string: Unicode character sequence"
-        ],
-        "name": "https://w3id.org/cwl/salad#PrimitiveType",
-        "symbols": [
-            "https://w3id.org/cwl/salad#null",
-            "http://www.w3.org/2001/XMLSchema#boolean",
-            "http://www.w3.org/2001/XMLSchema#int",
-            "http://www.w3.org/2001/XMLSchema#long",
-            "http://www.w3.org/2001/XMLSchema#float",
-            "http://www.w3.org/2001/XMLSchema#double",
-            "http://www.w3.org/2001/XMLSchema#string"
         ]
     },
     {
-        "type": "enum",
-        "docAfter": "https://w3id.org/cwl/salad#PrimitiveType",
-        "doc": "The **Any** type validates for any non-null value.\n",
         "name": "https://w3id.org/cwl/salad#Any",
+        "type": "enum",
         "symbols": [
             "https://w3id.org/cwl/salad#Any"
-        ]
+        ],
+        "docAfter": "https://w3id.org/cwl/salad#PrimitiveType",
+        "doc": "The **Any** type validates for any non-null value.\n"
     },
     {
+        "name": "https://w3id.org/cwl/salad#RecordField",
         "type": "record",
+        "extends": "https://w3id.org/cwl/salad#Documented",
+        "doc": "A field of a record.",
         "fields": [
             {
-                "type": "string",
-                "doc": "The name of the field\n",
                 "name": "https://w3id.org/cwl/salad#RecordField/name",
-                "jsonldPredicate": "@id"
+                "type": "string",
+                "jsonldPredicate": "@id",
+                "doc": "The name of the field\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#RecordField/type",
                 "type": [
                     "PrimitiveType",
                     "RecordSchema",
@@ -141,51 +145,47 @@
                     "ArraySchema",
                     "string",
                     {
+                        "type": "array",
                         "items": [
                             "PrimitiveType",
                             "RecordSchema",
                             "EnumSchema",
                             "ArraySchema",
                             "string"
-                        ],
-                        "type": "array"
+                        ]
                     }
                 ],
-                "doc": "The field type\n",
-                "name": "https://w3id.org/cwl/salad#RecordField/type",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#type",
                     "_type": "@vocab",
                     "typeDSL": true,
                     "refScope": 2
-                }
+                },
+                "doc": "The field type\n"
             }
-        ],
-        "doc": "A field of a record.",
-        "name": "https://w3id.org/cwl/salad#RecordField",
-        "extends": "https://w3id.org/cwl/salad#Documented"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#RecordSchema",
         "type": "record",
         "fields": [
             {
-                "name": "https://w3id.org/cwl/salad#RecordSchema/fields",
-                "doc": "Defines the fields of the record.",
                 "type": [
                     "null",
                     {
-                        "items": "RecordField",
-                        "type": "array"
+                        "type": "array",
+                        "items": "RecordField"
                     }
                 ],
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#fields",
                     "mapSubject": "name",
                     "mapPredicate": "type"
-                }
+                },
+                "doc": "Defines the fields of the record.",
+                "name": "https://w3id.org/cwl/salad#RecordSchema/fields"
             },
             {
-                "name": "https://w3id.org/cwl/salad#RecordSchema/type",
                 "doc": "Must be `record`",
                 "type": {
                     "type": "enum",
@@ -198,29 +198,30 @@
                     "_type": "@vocab",
                     "typeDSL": true,
                     "refScope": 2
-                }
+                },
+                "name": "https://w3id.org/cwl/salad#RecordSchema/type"
             }
-        ],
-        "name": "https://w3id.org/cwl/salad#RecordSchema"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#EnumSchema",
         "type": "record",
+        "doc": "Define an enumerated type.\n",
         "fields": [
             {
-                "name": "https://w3id.org/cwl/salad#EnumSchema/symbols",
-                "doc": "Defines the set of valid symbols.",
                 "type": {
-                    "items": "string",
-                    "type": "array"
+                    "type": "array",
+                    "items": "string"
                 },
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#symbols",
                     "_type": "@id",
                     "identity": true
-                }
+                },
+                "doc": "Defines the set of valid symbols.",
+                "name": "https://w3id.org/cwl/salad#EnumSchema/symbols"
             },
             {
-                "name": "https://w3id.org/cwl/salad#EnumSchema/type",
                 "doc": "Must be `enum`",
                 "type": {
                     "type": "enum",
@@ -233,18 +234,16 @@
                     "_type": "@vocab",
                     "typeDSL": true,
                     "refScope": 2
-                }
+                },
+                "name": "https://w3id.org/cwl/salad#EnumSchema/type"
             }
-        ],
-        "doc": "Define an enumerated type.\n",
-        "name": "https://w3id.org/cwl/salad#EnumSchema"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#ArraySchema",
         "type": "record",
         "fields": [
             {
-                "name": "https://w3id.org/cwl/salad#ArraySchema/items",
-                "doc": "Defines the type of the array elements.",
                 "type": [
                     "PrimitiveType",
                     "RecordSchema",
@@ -252,24 +251,25 @@
                     "ArraySchema",
                     "string",
                     {
+                        "type": "array",
                         "items": [
                             "PrimitiveType",
                             "RecordSchema",
                             "EnumSchema",
                             "ArraySchema",
                             "string"
-                        ],
-                        "type": "array"
+                        ]
                     }
                 ],
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#items",
                     "_type": "@vocab",
                     "refScope": 2
-                }
+                },
+                "doc": "Defines the type of the array elements.",
+                "name": "https://w3id.org/cwl/salad#ArraySchema/items"
             },
             {
-                "name": "https://w3id.org/cwl/salad#ArraySchema/type",
                 "doc": "Must be `array`",
                 "type": {
                     "type": "enum",
@@ -282,118 +282,119 @@
                     "_type": "@vocab",
                     "typeDSL": true,
                     "refScope": 2
-                }
+                },
+                "name": "https://w3id.org/cwl/salad#ArraySchema/type"
             }
-        ],
-        "name": "https://w3id.org/cwl/salad#ArraySchema"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#JsonldPredicate",
         "type": "record",
+        "doc": "Attached to a record field to define how the parent record field is handled for\nURI resolution and JSON-LD context generation.\n",
         "fields": [
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/_id",
                 "type": [
                     "null",
                     "string"
                 ],
-                "doc": "The predicate URI that this field corresponds to.\nCorresponds to JSON-LD `@id` directive.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/_id",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#_id",
                     "_type": "@id",
                     "identity": true
-                }
+                },
+                "doc": "The predicate URI that this field corresponds to.\nCorresponds to JSON-LD `@id` directive.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/_type",
                 "type": [
                     "null",
                     "string"
                 ],
-                "doc": "The context type hint, corresponds to JSON-LD `@type` directive.\n\n* If the value of this field is `@id` and `identity` is false or\nunspecified, the parent field must be resolved using the link\nresolution rules.  If `identity` is true, the parent field must be\nresolved using the identifier expansion rules.\n\n* If the value of this field is `@vocab`, the parent field must be\n  resolved using the vocabulary resolution rules.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/_type"
+                "doc": "The context type hint, corresponds to JSON-LD `@type` directive.\n\n* If the value of this field is `@id` and `identity` is false or\nunspecified, the parent field must be resolved using the link\nresolution rules.  If `identity` is true, the parent field must be\nresolved using the identifier expansion rules.\n\n* If the value of this field is `@vocab`, the parent field must be\n  resolved using the vocabulary resolution rules.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/_container",
                 "type": [
                     "null",
                     "string"
                 ],
-                "doc": "Structure hint, corresponds to JSON-LD `@container` directive.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/_container"
+                "doc": "Structure hint, corresponds to JSON-LD `@container` directive.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/identity",
                 "type": [
                     "null",
                     "boolean"
                 ],
-                "doc": "If true and `_type` is `@id` this indicates that the parent field must\nbe resolved according to identity resolution rules instead of link\nresolution rules.  In addition, the field value is considered an\nassertion that the linked value exists; absence of an object in the loaded document\nwith the URI is not an error.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/identity"
+                "doc": "If true and `_type` is `@id` this indicates that the parent field must\nbe resolved according to identity resolution rules instead of link\nresolution rules.  In addition, the field value is considered an\nassertion that the linked value exists; absence of an object in the loaded document\nwith the URI is not an error.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/noLinkCheck",
                 "type": [
                     "null",
                     "boolean"
                 ],
-                "doc": "If true, this indicates that link validation traversal must stop at\nthis field.  This field (it is is a URI) or any fields under it (if it\nis an object or array) are not subject to link checking.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/noLinkCheck"
+                "doc": "If true, this indicates that link validation traversal must stop at\nthis field.  This field (it is is a URI) or any fields under it (if it\nis an object or array) are not subject to link checking.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/mapSubject",
                 "type": [
                     "null",
                     "string"
                 ],
-                "doc": "If the value of the field is a JSON object, it must be transformed\ninto an array of JSON objects, where each key-value pair from the\nsource JSON object is a list item, the list items must be JSON objects,\nand the key is assigned to the field specified by `mapSubject`.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/mapSubject"
+                "doc": "If the value of the field is a JSON object, it must be transformed\ninto an array of JSON objects, where each key-value pair from the\nsource JSON object is a list item, the list items must be JSON objects,\nand the key is assigned to the field specified by `mapSubject`.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/mapPredicate",
                 "type": [
                     "null",
                     "string"
                 ],
-                "doc": "Only applies if `mapSubject` is also provided.  If the value of the\nfield is a JSON object, it is transformed as described in `mapSubject`,\nwith the addition that when the value of a map item is not an object,\nthe item is transformed to a JSON object with the key assigned to the\nfield specified by `mapSubject` and the value assigned to the field\nspecified by `mapPredicate`.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/mapPredicate"
+                "doc": "Only applies if `mapSubject` is also provided.  If the value of the\nfield is a JSON object, it is transformed as described in `mapSubject`,\nwith the addition that when the value of a map item is not an object,\nthe item is transformed to a JSON object with the key assigned to the\nfield specified by `mapSubject` and the value assigned to the field\nspecified by `mapPredicate`.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/refScope",
                 "type": [
                     "null",
                     "int"
                 ],
-                "doc": "If the field contains a relative reference, it must be resolved by\nsearching for valid document references in each successive parent scope\nin the document fragment.  For example, a reference of `foo` in the\ncontext `#foo/bar/baz` will first check for the existence of\n`#foo/bar/baz/foo`, followed by `#foo/bar/foo`, then `#foo/foo` and\nthen finally `#foo`.  The first valid URI in the search order shall be\nused as the fully resolved value of the identifier.  The value of the\nrefScope field is the specified number of levels from the containing\nidentifer scope before starting the search, so if `refScope: 2` then\n\"baz\" and \"bar\" must be stripped to get the base `#foo` and search\n`#foo/foo` and the `#foo`.  The last scope searched must be the top\nlevel scope before determining if the identifier cannot be resolved.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/refScope"
+                "doc": "If the field contains a relative reference, it must be resolved by\nsearching for valid document references in each successive parent scope\nin the document fragment.  For example, a reference of `foo` in the\ncontext `#foo/bar/baz` will first check for the existence of\n`#foo/bar/baz/foo`, followed by `#foo/bar/foo`, then `#foo/foo` and\nthen finally `#foo`.  The first valid URI in the search order shall be\nused as the fully resolved value of the identifier.  The value of the\nrefScope field is the specified number of levels from the containing\nidentifer scope before starting the search, so if `refScope: 2` then\n\"baz\" and \"bar\" must be stripped to get the base `#foo` and search\n`#foo/foo` and the `#foo`.  The last scope searched must be the top\nlevel scope before determining if the identifier cannot be resolved.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/typeDSL",
                 "type": [
                     "null",
                     "boolean"
                 ],
-                "doc": "Field must be expanded based on the the Schema Salad type DSL.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/typeDSL"
+                "doc": "Field must be expanded based on the the Schema Salad type DSL.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/secondaryFilesDSL",
                 "type": [
                     "null",
                     "boolean"
                 ],
-                "doc": "Field must be expanded based on the the Schema Salad secondary file DSL.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/secondaryFilesDSL"
+                "doc": "Field must be expanded based on the the Schema Salad secondary file DSL.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#JsonldPredicate/subscope",
                 "type": [
                     "null",
                     "string"
                 ],
-                "doc": "Append the subscope to the current scope when performing\nidentifier resolution to objects under this field.\n",
-                "name": "https://w3id.org/cwl/salad#JsonldPredicate/subscope"
+                "doc": "Append the subscope to the current scope when performing\nidentifier resolution to objects under this field.\n"
             }
-        ],
-        "doc": "Attached to a record field to define how the parent record field is handled for\nURI resolution and JSON-LD context generation.\n",
-        "name": "https://w3id.org/cwl/salad#JsonldPredicate"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#SpecializeDef",
         "type": "record",
         "fields": [
             {
+                "name": "https://w3id.org/cwl/salad#SpecializeDef/specializeFrom",
                 "type": "string",
                 "doc": "The data type to be replaced",
-                "name": "https://w3id.org/cwl/salad#SpecializeDef/specializeFrom",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#specializeFrom",
                     "_type": "@id",
@@ -401,252 +402,257 @@
                 }
             },
             {
+                "name": "https://w3id.org/cwl/salad#SpecializeDef/specializeTo",
                 "type": "string",
                 "doc": "The new data type to replace with",
-                "name": "https://w3id.org/cwl/salad#SpecializeDef/specializeTo",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#specializeTo",
                     "_type": "@id",
                     "refScope": 1
                 }
             }
-        ],
-        "name": "https://w3id.org/cwl/salad#SpecializeDef"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#NamedType",
         "type": "record",
         "abstract": true,
-        "name": "https://w3id.org/cwl/salad#NamedType",
+        "docParent": "https://w3id.org/cwl/salad#Schema",
         "fields": [
             {
-                "type": "string",
-                "doc": "The identifier for this type",
                 "name": "https://w3id.org/cwl/salad#NamedType/name",
-                "jsonldPredicate": "@id"
+                "type": "string",
+                "jsonldPredicate": "@id",
+                "doc": "The identifier for this type"
             },
             {
+                "name": "https://w3id.org/cwl/salad#NamedType/inVocab",
                 "type": [
                     "null",
                     "boolean"
                 ],
                 "default": true,
-                "name": "https://w3id.org/cwl/salad#NamedType/inVocab",
                 "doc": "If \"true\" (the default), include the short name of this type\nin the vocabulary.  The vocabulary are all the symbols (field\nnames and other identifiers, such as classes and enum values)\nwhich can be used in the document without a namespace prefix.\nThese are the keys of the JSON-LD context.  If false, do not\ninclude the short name in the vocabulary.\n\nThis is useful for specifying schema extensions that will be\nincluded in validation without introducing ambiguity by\nintroducing non-standard terms into the vocabulary.\n"
             }
-        ],
-        "docParent": "https://w3id.org/cwl/salad#Schema"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#DocType",
+        "type": "record",
+        "extends": "https://w3id.org/cwl/salad#Documented",
+        "abstract": true,
+        "docParent": "https://w3id.org/cwl/salad#Schema",
         "fields": [
             {
+                "name": "https://w3id.org/cwl/salad#DocType/docParent",
                 "type": [
                     "null",
                     "string"
                 ],
                 "doc": "Hint to indicate that during documentation generation, documentation\nfor this type should appear in a subsection under `docParent`.\n",
-                "name": "https://w3id.org/cwl/salad#DocType/docParent",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#docParent",
                     "_type": "@id"
                 }
             },
             {
+                "name": "https://w3id.org/cwl/salad#DocType/docChild",
                 "type": [
                     "null",
                     "string",
                     {
-                        "items": "string",
-                        "type": "array"
+                        "type": "array",
+                        "items": "string"
                     }
                 ],
                 "doc": "Hint to indicate that during documentation generation, documentation\nfor `docChild` should appear in a subsection under this type.\n",
-                "name": "https://w3id.org/cwl/salad#DocType/docChild",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#docChild",
                     "_type": "@id"
                 }
             },
             {
+                "name": "https://w3id.org/cwl/salad#DocType/docAfter",
                 "type": [
                     "null",
                     "string"
                 ],
                 "doc": "Hint to indicate that during documentation generation, documentation\nfor this type should appear after the `docAfter` section at the same\nlevel.\n",
-                "name": "https://w3id.org/cwl/salad#DocType/docAfter",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#docAfter",
                     "_type": "@id"
                 }
             }
-        ],
-        "docParent": "https://w3id.org/cwl/salad#Schema",
-        "name": "https://w3id.org/cwl/salad#DocType",
-        "abstract": true,
-        "type": "record",
-        "extends": "https://w3id.org/cwl/salad#Documented"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#SchemaDefinedType",
+        "type": "record",
+        "extends": "https://w3id.org/cwl/salad#DocType",
+        "doc": "Abstract base for schema-defined types.\n",
+        "abstract": true,
         "fields": [
             {
+                "name": "https://w3id.org/cwl/salad#SchemaDefinedType/jsonldPredicate",
                 "type": [
                     "null",
                     "string",
                     "JsonldPredicate"
                 ],
                 "doc": "Annotate this type with linked data context.\n",
-                "name": "https://w3id.org/cwl/salad#SchemaDefinedType/jsonldPredicate",
                 "jsonldPredicate": "sld:jsonldPredicate"
             },
             {
+                "name": "https://w3id.org/cwl/salad#SchemaDefinedType/documentRoot",
                 "type": [
                     "null",
                     "boolean"
                 ],
-                "doc": "If true, indicates that the type is a valid at the document root.  At\nleast one type in a schema must be tagged with `documentRoot: true`.\n",
-                "name": "https://w3id.org/cwl/salad#SchemaDefinedType/documentRoot"
+                "doc": "If true, indicates that the type is a valid at the document root.  At\nleast one type in a schema must be tagged with `documentRoot: true`.\n"
             }
-        ],
-        "name": "https://w3id.org/cwl/salad#SchemaDefinedType",
-        "abstract": true,
-        "doc": "Abstract base for schema-defined types.\n",
-        "type": "record",
-        "extends": "https://w3id.org/cwl/salad#DocType"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#SaladRecordField",
         "type": "record",
+        "extends": "https://w3id.org/cwl/salad#RecordField",
+        "doc": "A field of a record.",
         "fields": [
             {
+                "name": "https://w3id.org/cwl/salad#SaladRecordField/jsonldPredicate",
                 "type": [
                     "null",
                     "string",
                     "JsonldPredicate"
                 ],
                 "doc": "Annotate this type with linked data context.\n",
-                "name": "https://w3id.org/cwl/salad#SaladRecordField/jsonldPredicate",
                 "jsonldPredicate": "sld:jsonldPredicate"
             },
             {
+                "name": "https://w3id.org/cwl/salad#SaladRecordField/default",
                 "type": [
                     "null",
                     "Any"
                 ],
-                "doc": "The default value to use for this field if the field is missing or \"null\".\n",
-                "name": "https://w3id.org/cwl/salad#SaladRecordField/default",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#default",
                     "noLinkCheck": true
-                }
+                },
+                "doc": "The default value to use for this field if the field is missing or \"null\".\n"
             }
-        ],
-        "doc": "A field of a record.",
-        "name": "https://w3id.org/cwl/salad#SaladRecordField",
-        "extends": "https://w3id.org/cwl/salad#RecordField"
+        ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#SaladRecordSchema",
+        "docParent": "https://w3id.org/cwl/salad#Schema",
+        "type": "record",
+        "extends": [
+            "https://w3id.org/cwl/salad#NamedType",
+            "https://w3id.org/cwl/salad#RecordSchema",
+            "https://w3id.org/cwl/salad#SchemaDefinedType"
+        ],
+        "documentRoot": true,
         "specialize": [
             {
-                "specializeFrom": "https://w3id.org/cwl/salad#RecordField",
-                "specializeTo": "https://w3id.org/cwl/salad#SaladRecordField"
+                "specializeTo": "https://w3id.org/cwl/salad#SaladRecordField",
+                "specializeFrom": "https://w3id.org/cwl/salad#RecordField"
             }
         ],
-        "docParent": "https://w3id.org/cwl/salad#Schema",
-        "documentRoot": true,
-        "name": "https://w3id.org/cwl/salad#SaladRecordSchema",
         "fields": [
             {
+                "name": "https://w3id.org/cwl/salad#SaladRecordSchema/abstract",
                 "type": [
                     "null",
                     "boolean"
                 ],
-                "doc": "If true, this record is abstract and may be used as a base for other\nrecords, but is not valid on its own.\n",
-                "name": "https://w3id.org/cwl/salad#SaladRecordSchema/abstract"
+                "doc": "If true, this record is abstract and may be used as a base for other\nrecords, but is not valid on its own.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#SaladRecordSchema/extends",
                 "type": [
                     "null",
                     "string",
                     {
-                        "items": "string",
-                        "type": "array"
+                        "type": "array",
+                        "items": "string"
                     }
                 ],
-                "doc": "Indicates that this record inherits fields from one or more base records.\n",
-                "name": "https://w3id.org/cwl/salad#SaladRecordSchema/extends",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#extends",
                     "_type": "@id",
                     "refScope": 1
-                }
+                },
+                "doc": "Indicates that this record inherits fields from one or more base records.\n"
             },
             {
+                "name": "https://w3id.org/cwl/salad#SaladRecordSchema/specialize",
                 "type": [
                     "null",
                     {
-                        "items": "SpecializeDef",
-                        "type": "array"
+                        "type": "array",
+                        "items": "SpecializeDef"
                     }
                 ],
                 "doc": "Only applies if `extends` is declared.  Apply type specialization using the\nbase record as a template.  For each field inherited from the base\nrecord, replace any instance of the type `specializeFrom` with\n`specializeTo`.\n",
-                "name": "https://w3id.org/cwl/salad#SaladRecordSchema/specialize",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#specialize",
                     "mapSubject": "specializeFrom",
                     "mapPredicate": "specializeTo"
                 }
             }
-        ],
-        "type": "record",
-        "extends": [
-            "https://w3id.org/cwl/salad#NamedType",
-            "https://w3id.org/cwl/salad#RecordSchema",
-            "https://w3id.org/cwl/salad#SchemaDefinedType"
         ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#SaladEnumSchema",
         "docParent": "https://w3id.org/cwl/salad#Schema",
+        "type": "record",
+        "extends": [
+            "https://w3id.org/cwl/salad#NamedType",
+            "https://w3id.org/cwl/salad#EnumSchema",
+            "https://w3id.org/cwl/salad#SchemaDefinedType"
+        ],
         "documentRoot": true,
-        "name": "https://w3id.org/cwl/salad#SaladEnumSchema",
+        "doc": "Define an enumerated type.\n",
         "fields": [
             {
+                "name": "https://w3id.org/cwl/salad#SaladEnumSchema/extends",
                 "type": [
                     "null",
                     "string",
                     {
-                        "items": "string",
-                        "type": "array"
+                        "type": "array",
+                        "items": "string"
                     }
                 ],
-                "doc": "Indicates that this enum inherits symbols from a base enum.\n",
-                "name": "https://w3id.org/cwl/salad#SaladEnumSchema/extends",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#extends",
                     "_type": "@id",
                     "refScope": 1
-                }
+                },
+                "doc": "Indicates that this enum inherits symbols from a base enum.\n"
             }
-        ],
-        "doc": "Define an enumerated type.\n",
-        "type": "record",
-        "extends": [
-            "https://w3id.org/cwl/salad#NamedType",
-            "https://w3id.org/cwl/salad#EnumSchema",
-            "https://w3id.org/cwl/salad#SchemaDefinedType"
         ]
     },
     {
+        "name": "https://w3id.org/cwl/salad#Documentation",
+        "type": "record",
         "docParent": "https://w3id.org/cwl/salad#Schema",
+        "extends": [
+            "https://w3id.org/cwl/salad#NamedType",
+            "https://w3id.org/cwl/salad#DocType"
+        ],
         "documentRoot": true,
-        "name": "https://w3id.org/cwl/salad#Documentation",
+        "doc": "A documentation section.  This type exists to facilitate self-documenting\nschemas but has no role in formal validation.\n",
         "fields": [
             {
+                "name": "https://w3id.org/cwl/salad#Documentation/type",
+                "doc": "Must be `documentation`",
                 "type": {
                     "type": "enum",
                     "symbols": [
                         "https://w3id.org/cwl/salad#documentation"
                     ]
                 },
-                "doc": "Must be `documentation`",
-                "name": "https://w3id.org/cwl/salad#Documentation/type",
                 "jsonldPredicate": {
                     "_id": "https://w3id.org/cwl/salad#type",
                     "_type": "@vocab",
@@ -654,12 +660,6 @@
                     "refScope": 2
                 }
             }
-        ],
-        "doc": "A documentation section.  This type exists to facilitate self-documenting\nschemas but has no role in formal validation.\n",
-        "type": "record",
-        "extends": [
-            "https://w3id.org/cwl/salad#NamedType",
-            "https://w3id.org/cwl/salad#DocType"
         ]
     }
 ]