Document how to use diagnostics in libraries (#1896)

This commit is contained in:
Timothee Guerin 2023-05-05 14:17:53 -07:00 коммит произвёл GitHub
Родитель 362994e4da
Коммит caaf0e85a7
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 129 добавлений и 3 удалений

Просмотреть файл

@ -0,0 +1,125 @@
# Diagnostics
TypeSpec compiler report errors and warnings in the spec using the diagnostic API.
## Best practices
- ❌ Do not use `throw` to report errors. Any exception thrown like this will be presented as a bug in your library to the user.
- ✅ Use diagnostic API to report expected errors and warnings.
- ✅ Use `reportDiagnostic` in a decorator, `$onValidate` or `$onEmit`
- ❌ Do not use `reportDiagnostic` in an accessor(A function meant to be consumed in another library or emitter). See [collect diagnostics section](#collect-diagnostics)
## Diagnostic specification
- Each diagnostic MUST have a `code`. The full code is the the library name followed by the declared code. (`<lib-name>/<local-code>`)
- Each diagnostic MUST have a `severity`. It can be `error`, `warning`. Errors cannot be suppressed
- Each diagnostics MUST have at least one message. Using `default` as the `messageId` will allow it to be the default selected.
- Each diagnostics message MAY have parameters to interpolate information into the message
## Usage
### Declare the diagnostics you are reporting
```ts
// in lib.js
export const { reportDiagnostic, createDiagnostic, createStateSymbol } = createTypeSpecLibrary({
name: "@typespec/my-lib",
diagnostics: {
// Basic diagnostic with a fixed message
"no-array": {
severity: "error",
messages: {
default: `Array is not allowed in my-lib models.`,
},
},
// Parameterized message
"duplicate-route": {
severity: "error",
messages: {
default: paramMessage`Route '${"path"}' is being referenced in 2 different operations.`,
},
},
// Multiple messages
"duplicate-name": {
severity: "warning",
messages: {
default: paramMessage`Duplicate type name: '${"value"}'.`,
parameter: paramMessage`Duplicate parameter key: '${"value"}'.`,
},
},
},
} as const);
```
This will represent 3 different diagnostics with full name of
- `@typespec/my-lib/no-array`
- `@typespec/my-lib/duplicate-route`
- `@typespec/my-lib/duplicate-name`
### Report diagnostics
```ts
import { reportDiagnostic } from "./lib.js";
// Basic diagnostic with a fixed message
reportDiagnostic(program, {
code: "no-array",
target: diagnosticTarget,
});
// Parameterized message
reportDiagnostic(program, {
code: "duplicate-route",
format: {path: "/foo"}
target: diagnosticTarget,
});
// Multiple messages
reportDiagnostic(program, {
code: "duplicate-name",
messageId: "parmaeter",
format: {value: "$select"},
target: diagnosticTarget,
});
```
### Collect diagnostics
When trying to report diagnostic in an accessor a good pattern is not to report the diagnostic to the program directly but return a tuple to let the user decide what to do.
This prevent duplicate diagnostics emitter if the accessor is called multiple times.
```ts
import { createDiagnosticCollector, Diagnostic } from "@typespec/compiler";
function getRoutes(): [Route, readonly Diagnostic] {
const diagnostics = createDiagnosticCollector();
diagnostics.add(
createDiagnostic(program, {
code: "no-array",
target: diagnosticTarget,
})
);
const result = diagnostic.pipe(getParameters()); // to pipe diagnostics returned by `getParameters`
return diagnostics.wrap(routes);
}
```
or manually
```ts
import { createDiagnosticCollector, Diagnostic } from "@typespec/compiler";
function getRoutes(): [Route, readonly Diagnostic] {
const diagnostics = [];
diagnostics.push(
createDiagnostic(program, {
code: "no-array",
target: diagnosticTarget,
})
);
return [routes, diagnostics];
}
```

Просмотреть файл

@ -9,7 +9,7 @@ jobs:
name: azsdk-pool-mms-ubuntu-2004-general
vmImage: ubuntu-20.04
variables:
CADL_WEBSITE_BASE_PATH: "prs/$(System.PullRequest.PullRequestNumber)/"
TYPESPEC_WEBSITE_BASE_PATH: "prs/$(System.PullRequest.PullRequestNumber)/"
steps:
- checkout: self
persistCredentials: true
@ -34,7 +34,7 @@ jobs:
az storage blob upload-batch \
--destination \$web \
--account-name "cadlplayground" \
--destination-path $(CADL_WEBSITE_BASE_PATH) \
--destination-path $(TYPESPEC_WEBSITE_BASE_PATH) \
--source "./packages/playground/dist/" \
--overwrite
@ -47,7 +47,7 @@ jobs:
az storage blob upload-batch \
--destination \$web \
--account-name "cadlwebsite" \
--destination-path $(CADL_WEBSITE_BASE_PATH) \
--destination-path $(TYPESPEC_WEBSITE_BASE_PATH) \
--source "./packages/website/build/" \
--overwrite

Просмотреть файл

@ -134,6 +134,7 @@ const sidebars = {
label: "Writing TypeSpec Libraries",
items: [
"extending-typespec/basics",
"extending-typespec/diagnostics",
"extending-typespec/create-decorators",
"extending-typespec/linters",
"extending-typespec/emitters",