Skip to content
Mikayla Hutchinson edited this page Apr 19, 2024 · 1 revision

A .buildschema.json file is in the jsonc format, supporting comments and trailing commas.

It contains a JSON object with the following top-level keys, which are all optional. These keys mainly contain collections of definitions for symbols: properties, items, targets, metadata, custom types, and custom type values.

{
  "license": "Copyright information", // this is purely informative for viewers of the file, so you could use a comment instead
  "intellisenseImports": [
    // additional schemas to be imported only when directly editing the file for which this is a sidecar
  ],
  "properties": {
    // definitions of properties
  },
  "items": {
    // definitions of items and their metadata
  },
  "targets": {
    // definitions of properties
  },
  "metadata": {
    // definitions of metadata that applies to multiple items or to items defined in other schemas
  },
  "types": {
    // definitions of custom types
  },
}

For details on these symbol definitions, see the sections on Property Definitions, Item Definitions, Metadata Definitions, Target Definitions, and Type Definitions.

Examples of build schemas can be found in the MSBuild Editor's built-in schemas and in the T4.BuildTools NuGet package.

Common Keys

Symbol definitions are in the form of JSON objects. The description, type, isList, listSeparators, helpUrl, and deprecationMessage keys are used in multiple symbol definitions and are described together in this section.

description

The description key has a string value that contains documentation for display in tooltips. Description strings support a subset of Markdown: inline `code`, *emphasis*, and **strong** formatting.

Where a definition contains only a description, and no other keys, it may be simplified to a short form that contains only the description string instead of a JSON object. For example, the following two property definitions are equivalent:

"MyFirstProperty": "My first description",
"MySecondProperty": {
  "description": "My second property description",
}

helpUrl

The helpUrl key in a symbol definition provides a link to web documentation for that symbol. This is displayed in tooltips and will be opened when using F1 help.

deprecationMessage

The deprecationMessage key in a symbol definition marks that symbol as deprecated. When this key is used, its value cannot be null or empty. The deprecation message will be shown as a warning in the editor when using a deprecated symbol. The deprecation message uses the same subset of Markdown as is used by description.

type

The type key in a symbol definition provides a type annotation for that symbol. Type annotations are displayed in tooltips, and are used for validation and IntelliSense. A type annotation may use an intrinsic type, reference a shared type, or define a custom type inline.

For example, a property could be annotated with the intrinsic type folder-with-slash, indicating that it contains a directory path with a trailing slash.

"MyProperty": {
  "type": "folder-with-slash"
}

For details about the different kinds of type annotations, see Type Annotations.

Symbols defined in a schema that do not have a type annotation will be treated as having an unknown type. Note that inferred schemas will infer type information from symbol names, for example property names that end with Path will be treated as having type file-or-folder. However, this inference is not performed for symbols defined in build schema files.

isList

The isList key is a boolean that specifies whether the value of a symbol is a list. A list value may contain multiple values separated by a list separator.

Marking a symbol as a list enables the editor to provide IntelliSense for the list values, and to validate that the list values are of the correct type. For example, if a property is marked as a list of int, the editor will validate that all the values in the list are integers. The editor will also warn when list-like values are used for symbols that are not marked as lists.

listSeparator

Lists are a pattern that is common in MSBuild properties and metadata, but is not explicitly supported by the MSBuild engine. This means that the handling of lists is not standardized, and is up to the individual MSBuild tasks or expressions that are used to interpret the value. Some use semicolons as separators, some use commas, and some use both. Some trim whitespace from the list values, and some do not.

The default list separator for list values is a semicolon as this is commonly used for consistency with MSBuild's built-in item splitting. However, the listSeparators key can be used to override the list separator for an individual list value. The value of listSeparators is a string that specifies the separator characters for the list. Currently only the values ";", ",", and ";," are supported. If the listSeparators key is present then the isList key is implied and may be omitted.

defaultValue

The defaultValue key is a string that specifies the default value of a property or item metadata. This enables the editor to show a warning when assigning the default value to a property, and a fix that removes the redundant assignment.

This is imperfect as it does not support default values that are computed dynamically, but it is a useful feature for the many properties that do have static default values. Support for dynamically determining default values may be added in the future. However, this key will remain relevant for cases where the default value is computed inside a task that consumes the property or metadata.

Property Definitions

The top-level properties collection contains property definitions. The keys are the property names, and the values are the property definitions.

A property definition may use a short form, where it is a string that is treated as a description of the property:

"properties": {
  "MyProperty": "Description of the property"
}

A full property definition is a JSON object that takes the following form:

"properties": {
  "MyProperty": {
    "description": "Description of the property",
    "type": "string",
    "isList": true,
    "listSeparators": ";",
    "defaultValue": "Default value",
    "isLiteral": true,
    "deprecationMessage": "This property is deprecated",
    "helpUrl": "https://example.com"
  }
}

The keys description, type, isList, listSeparators, defaulValue, helpUrl, and deprecationMessage are common keys. Other keys are described below. All these keys are optional.

isLiteral

The isLiteral key is a boolean that specifies whether the property permits only literal values (i.e. no expressions). By default, isLiteral is false. This is generally only used for properties in project files that are expected to be read by other tooling that reads project files directly as XML files without using the MSBuild engine to evaluate expressions. Examples include the ProjectTypeGuids property in older C# projects that use the legacy Managed Project System.

Items

The top-level items collection contains item definitions. The keys are the item names, and the values are the item definitions.

An item definition may use a short form, where it is a string that is treated as a description of the item:

"items": {
  "MyItem": "Description of the item"
}

A full item definition is a JSON object that takes the following form:

"items": {
  "MyItem": {
    "description": "Description of the item",
    "includeDescription": "Describes the item values listed in the Include attribute",
    "type": "string",
    "metadata": {
      "MyMetadata": {
        "description": "Description of the metadata",
        "type": "string",
        // more keys permitted, see Metadata section
      }
    },
    "packageType": "Dependency",
    "isSingleton": true,
    "deprecationMessage": "This item is deprecated",
    "helpUrl": "https://example.com"
  }
}

The keys description, type, isList, listSeparators, defaulValue, helpUrl, and deprecationMessage are common keys. Other keys are described below. All these keys are optional.

includeDescription

The includeDescription key is a string that describes the item values listed in the Include, Update, Exclude and Remove attribute. This is a plural noun expression that will used to generate customized description for the attribute. It supports the same subset of Markdown as is used by description.

For example, the includeDescription for the Compile item is "source files", which results in the following tooltips:

  • Include: "Semi-colon separated list of source files (wildcards are allowed) or other item references to include in this item list"
  • Exclude: "Semi-colon separated list of source files (wildcards are allowed) or other item references to exclude from the Include list"
  • Remove: "Semi-colon separated list of source files (wildcards are allowed) or other item references to remove from the existing list contents"
  • Update: "Semi-colon separated list of source files (wildcards are allowed) or other item references to be updated with the metadata from contained in this xml element"

These may vary based on the item type. For example, for the includeDescription for the PackageReference item is "NuGet package IDs", which results in the following tooltips:

  • Include: "Semi-colon separated list of NuGet package IDs or other item references to include in this item list"
  • Exclude: "Semi-colon separated list of NuGet package IDs or other item references to exclude from the Include list"
  • Remove: "Semi-colon separated list of NuGet package IDs or other item references to remove from the existing list contents"
  • Update: "Semi-colon separated list of NuGet package IDs or other item references to be updated with the metadata from contained in this xml element"

This may be extended in the future to better support localization.

metadata

The metadata key is a collection of metadata definitions for the item. The keys are the metadata names, and the values are the metadata definitions. For details of the definitions, see Metadata Definitions.

packageType

The packageType key is a string that restricts the package type for items of type nuget-id. The value is a string that is used to restrict the package type for items of type nuget-id. The value is used to provide IntelliSense for the package type when the item is of type nuget-id.

isSingleton

The isSingleton key is a boolean that specifies that there may only be a single value for this item. This behavior is rare and unidiomatic, as properties are generally used for singleton values. Examples of singleton items include the ApplicationDefinition item in WPF projects, and the BootstrapperPackage item in projects that use ClickOnce.

Metadata Definitions

The top-level metadata collection contains metadata definitions that apply to multiple items or to items defined in other schemas. Item definitions may contain a metadata collection that contains metadata definitions that apply only to that item.

For both of kinds of metadata collections, the keys are the metadata names, and the values are the metadata definitions. The metadata definitions also take the same form for both collections. The only difference is that top-level metadata definitions must also contain an $appliesTo key that specifies the item types to which the metadata applies. This key is not present in item-level metadata definitions, as the item type is implied by the item definition that contains the metadata collection. The value of $appliesTo is a string or an array of strings that are the names of the items to which the metadata applies.

A metadata definition takes the following form:

"metadata": {
  "MyMetadata": {
    "$appliesTo": [ "MyItem", "Compile" ], // only for top-level metadata definitions
    "description": "Description of the metadata",
    "type": "string",
    "isList": true,
    "listSeparators": ";",
    "defaultValue": "Default value",
    "isRequired": true,
    "deprecationMessage": "This metadata is deprecated",
    "helpUrl": "https://example.com"
  }
}

The keys description, type, isList, listSeparators, defaultValue, helpUrl, and deprecationMessage are common keys. Other keys are described below. All these keys are optional.

isRequired

The isRequired key is a boolean that specifies whether the metadata is required on all items of this type. By default, isRequired is false.

Target Definitions

The top-level targets collection contains target definitions. The keys are the target names, and the values are the target definitions. Target definitions currently only support the short form, where they are strings that are treated as a description of the target:

"targets": {
  "MyTarget": "Description of my target"
}

Type Annotations

Although MSBuild itself does not support typed symbols, the handling of properties, items, and metadata by tasks and expressions is often type-specific. For example, the Copy task expects a DestinationFiles property to be a list of files, and the Csc task expects a WarningLevel property to be an integer.

The MSBuild Editor allows schema authors to provide type annotations for symbols that provide information about the values that are expected for those symbols. Type annotations are used to provide improved IntelliSense and validation, and are also displayed in tooltips for symbols that use them. Type annotations are optional for all symbols that allow them, and symbols without type annotations are treated as having an unknown type.

The three different kinds of type annotations that can be used in a symbol definition are described below: intrinsic types, shared type references, and inline type definitions.

Intrinsic Types

A type annotation of the form "type": "folder-with-slash" is an example of using an intrinsic type. An intrinsic type is a type that that is defined within the MSBuild Editor itself. Other examples of intrinsic types include int, string, url, target-name, and so on. The full list of intrinsic types will not be given here, but all intrinsic types are documented in the JSON schema.

Some intrinsic types have special handling beyond validation. For example:

  • Symbols with the culture type have IntelliSense for .NET culture names
  • Symbols with the nuget-id type have package name IntelliSense based on dynamically querying NuGet.org, and a special tooltip displaying the package's description.
  • Symbols with the guid type have a special item in the completion list that allows generating a new GUID.

Shared Type References

A shared type is defined in the top-level types collection. The key for the definition is an ID that is not displayed to the user, and is only used to reference that shared type within the schema. Shared types are useful for defining complex types that are used by multiple symbols.

A type reference takes the form of an object with a single key, "$ref", with a value that is a JSON pointer to the shared type definition. Using a JSON pointer allows it to be validated by the JSON schema. Only JSON paths of the form #/types/myCustomTypeId are currently supported.

For example, this reference:

"type": { "$ref": "#/types/myCustomTypeId" }

would resolve to this shared type definition:

{
  "types": {
    "myCustomTypeId": [ "A", "B", "C" ]
  }
}

For the form that shared type definitions take within the top=level type collection, see Type Definitions.

Inline Type Definitions

Inline type definitions provide an easy way to define a custom type for use by a single symbol. Nontrivial type definitions and types that are expected to be used by multiple symbols should instead used a shared custom type.

Inline type definitions use the exact same form as shared type definitions, described in Type Definitions.

For example:

"MyFirstProperty": {
  "type": [ "A", "B" ]
},
"MySecondProperty": {
  "type": {
    "values": {
      "A": "A description",
      "B": "B description"
    }
  }
}

Type Definitions

A type definition is a JSON object that describes a custom type. A type definition takes the following form:

{
  "name": "typename",
  "description": "Type description",
  "values": {
    "A": "Description of A",
    "B": "Description of B",
    "C": {
      "description": "Description of C",
      "deprecationMessage": "C is deprecated",
      "helpUrl": "https://example.com",
      "aliases": [ "C2" ]
    }
  },
  "allowUnknownValues": true,
  "baseType": "guid",
  "caseSensitive": true,
  "helpUrl": "https://example.com",
  "analyzerHints": {
    "GuidFormat": "N"
  }
}

The keys description, helpUrl, and deprecationMessage are common keys. Other keys are described below.

Name

The type name is optional. If provided, it will be shown in the UI, for example in tooltips. If a type name is not provided, and the type definition has a baseType, then the base type will be used. Otherwise, the type will be displayed as an anonymous type. The name must be lowercase, and must start with a letter. It may contain letters, numbers, and dashes.

Values

The values key is a collection of values that the type can take, in the form of a JSON object, where the keys are the values themselves, and the values are definitions of those values

A value definition may use a short form, where it is a string that is treated as a description of the value.

The full form of a value definition is a JSON object that may contain the keys description, helpUrl, deprecationMessage, and aliases. The aliases key is an array of strings that are alternative names for the value. Aliases are not shown in completion lists, but are considered equivalent for validation and Find References. All these keys are optional.

Here is an example that uses both forms and all the keys:

"values": {
  "A": "Description of A",
  "B": "Description of B",
  "C": {
    "description": "Description of C",
    "deprecationMessage": "C is deprecated",
    "helpUrl": "https://example.com",
    "aliases": [ "C2" ]
  }
}

Allow Unknown Values

The allowUnknownValues key is a boolean that determines whether values not listed in the values collection are allowed. By default, allowUnknownValues is false, meaning the validator will flag any unknown values as errors.

Setting allowUnknownValues to true allows the type to be used with any value, while still providing completion, tooltips, and documentation for known values. If type definition uses a base type that can be validated, such as guid or int, the editor will still validate that unknown values conform to that base type.

Base Type

A custom type may have a baseType key that specifies an intrinsic type that the custom type is derived from. The base type is used for validation and IntelliSense. For example, a custom type that is derived from guid will inherit the validation rules for GUIDs and the special completion item that allows generating a new GUID.

Currently, the only intrinsic types that are permitted as base types are guid, int, and warning-code.

The warning-code base type is special, in that values of types that derive from warning-code will be used for completion and validation for symbols of the base warning-code type. This means that a custom type that derives from warning-code can be used to add values for the <NoWarn> property. For an example of this, see the C# warning codes schema.

This behavior is not present for other base types. For example, a type that derives from int will not be used for completion for symbols of the base int type.

Case Sensitivity

The caseSensitive key is a boolean that determines whether values of the type should be compared in a case-sensitive way. By default, caseSensitive is false, meaning that values are compared in a case-insensitive way.

Analyzer Hints

The analyzerHints key is a JSON object that contains additional hints for the MSBuild Editor's static analysis engine. These hints are used to provide additional validation for symbols that use the type. The keys in the analyzerHints object are specific to the base type of the custom type.

This object permits arbitrary keys, so custom values may be provided as hints for custom analyzers. The keys that are recognized by the MSBuild Editor's built-in validation and analyzers are documented in the JSON schema. For example, validation for the guid base type recognizes the GuidFormat key, which constrains a guid-derived type to a specific Guid.TryParseExact format.

"analyzerHints": {
  "GuidFormat": "B"
}