Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
changeKind: internal
packages:
- "@azure-tools/typespec-azure-core"
- "@azure-tools/typespec-azure-resource-manager"
- "@azure-tools/typespec-client-generator-core"
---

Migrate linter rule documentation to the tspd `docs` field so `tspd doc` auto-generates the per-rule reference pages. Rule extended docs now live next to each rule in `src/rules/<rule-name>.md` and are referenced via `docs: fileRef.fromPackageRoot(...)`. The generated pages keep their existing location (`libraries/<pkg>/rules/<rule-name>`) via the new `--rules-dir` tspd option, so rule URLs are unchanged. The generated pages are regenerated during the website build and are no longer tracked in git.
8 changes: 5 additions & 3 deletions .github/skills/create-linter-rule/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ This creates:

- `packages/<pkg>/src/rules/<rule-name>.ts` — rule skeleton
- `packages/<pkg>/test/rules/<rule-name>.test.ts` — test skeleton
- `website/src/content/docs/docs/libraries/<pkg>/rules/<rule-name>.md` — docs skeleton
- `packages/<pkg>/src/rules/<rule-name>.md` — docs skeleton (referenced from the rule via `docs: fileRef.fromPackageRoot(...)`)
- Updates `packages/<pkg>/src/linter.ts` — registers the rule

## Step 3: WRITE FAILING TESTS FIRST (TDD)
Expand Down Expand Up @@ -143,12 +143,14 @@ pnpm --filter "@azure-tools/typespec-azure-rulesets..." test

## Step 7: WRITE DOCUMENTATION AND REGENERATE DOCS

Edit `website/src/content/docs/docs/libraries/<pkg>/rules/<rule-name>.md`:
Edit `packages/<pkg>/src/rules/<rule-name>.md`:

- Replace all placeholder text
- Write a clear description of what the rule checks and why
- Provide realistic ❌ Incorrect and ✅ Correct examples using actual TypeSpec patterns
- Ensure the `Full name` code block shows the correct fully-qualified rule name
- This file holds only the extended documentation body — the page title, rule id, and
short description are generated from the rule definition. `tspd` renders the page at
`website/src/content/docs/docs/libraries/<pkg>/rules/<rule-name>.md`

Then regenerate the library's reference docs (updates the rule listing):

Expand Down
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -254,3 +254,8 @@ packages/typespec-java/emitter-tests/specs/**
packages/typespec-java/emitter-tests/node_modules/**
packages/typespec-java/emitter-tests/package-lock.json
packages/typespec-java/emitter-tests/tsp-spector-coverage-*.json

# Generated linter rule reference pages (produced by `tspd doc` / regen-docs via
# each rule's `docs` field). Regenerated during the website build (build:web), so
# they are not tracked. The rule source docs live in packages/*/src/rules/*.md.
website/src/content/docs/docs/libraries/*/rules/
2 changes: 1 addition & 1 deletion core
Submodule core updated 81 files
+7 −0 .chronus/changes/diagnostic-docs-openapi3-2026-6-9.md
+7 −0 .chronus/changes/init-template-source-2026-7-14-21-30-0.md
+15 −0 .chronus/changes/license-identifier-2026-7-20.md
+7 −0 .chronus/changes/reuse-template-source-loader-vscode-2026-7-18-14-55-0.md
+19 −0 .chronus/changes/rule-diagnostic-docs-compiler-2026-6-9.md
+7 −0 .chronus/changes/rule-diagnostic-docs-tspd-2026-6-9.md
+7 −0 .chronus/changes/rule-docs-http-2026-6-9.md
+7 −0 .chronus/changes/runner-remove-backup-path-2026-7-20-13-30-0.md
+7 −0 .chronus/changes/specs-addSse-2026-6-13-16-37-0.md
+7 −0 .chronus/changes/specs-addSse-2026-7-17-13-4-0.md
+7 −0 .chronus/changes/specs-addSse-2026-7-17-13-4-1.md
+7 −0 .chronus/changes/tspd-doc-rules-dir-option-2026-7-20-14-0-0.md
+1 −1 packages/compiler/cmd/tsp-server.js
+1 −1 packages/compiler/cmd/tsp.js
+31 −0 packages/compiler/src/core/file-ref.ts
+13 −0 packages/compiler/src/core/types.ts
+1 −0 packages/compiler/src/index.ts
+3 −9 packages/compiler/src/init/core-templates.ts
+56 −60 packages/compiler/src/init/init.ts
+10 −6 packages/compiler/src/init/scaffold.ts
+14 −0 packages/compiler/src/init/template-source/default-core-templates.ts
+55 −0 packages/compiler/src/init/template-source/in-memory-template-source.ts
+4 −0 packages/compiler/src/init/template-source/index.ts
+22 −0 packages/compiler/src/init/template-source/types.ts
+55 −0 packages/compiler/src/init/template-source/uri-template-source.ts
+3 −0 packages/compiler/src/internals/index.ts
+3 −12 packages/compiler/src/runner.ts
+40 −33 packages/compiler/test/cli/init.test.ts
+2 −1 packages/compiler/test/e2e/init-templates.e2e.ts
+88 −0 packages/compiler/test/init/template-source.test.ts
+35 −2 packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/EnumProvider.cs
+27 −0 ...http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/EnumProviders/EnumProviderTests.cs
+9 −0 ...erTests/BackCompat_ExtensibleEnumCustomCodeTakesPrecedenceOverPreservedUnderscores(Custom)/MockInputEnum.cs
+10 −0 ...iderTests/BackCompat_ExtensibleEnumCustomCodeTakesPrecedenceOverPreservedUnderscores(Last)/MockInputEnum.cs
+46 −0 ...rs/TestData/EnumProviderTests/BackCompat_ExtensibleEnumCustomCodeTakesPrecedenceOverPreservedUnderscores.cs
+2 −0 packages/http-specs/package.json
+75 −0 packages/http-specs/spec-summary.md
+153 −0 packages/http-specs/specs/streaming/sse/main.tsp
+71 −0 packages/http-specs/specs/streaming/sse/mockapi.ts
+38 −0 packages/http/src/rules/op-reference-container-route.md
+2 −1 packages/http/src/rules/op-reference-container-route.ts
+1 −0 packages/openapi/generated-defs/TypeSpec.OpenAPI.ts
+4 −1 packages/openapi/lib/decorators.tsp
+10 −0 packages/openapi/src/decorators.ts
+6 −0 packages/openapi/src/lib.ts
+7 −1 packages/openapi/src/types.ts
+36 −0 packages/openapi/test/decorators.test.ts
+13 −1 packages/openapi3/src/cli/actions/convert/transforms/transform-service-info.ts
+22 −0 packages/openapi3/src/diagnostics/duplicate-header.md
+19 −0 packages/openapi3/src/diagnostics/inline-cycle.md
+20 −0 packages/openapi3/src/diagnostics/invalid-schema.md
+14 −0 packages/openapi3/src/diagnostics/invalid-server-variable.md
+26 −0 packages/openapi3/src/diagnostics/path-query.md
+3 −0 packages/openapi3/src/diagnostics/union-null.md
+7 −1 packages/openapi3/src/lib.ts
+11 −1 packages/openapi3/src/openapi-spec-mappings.ts
+67 −2 packages/openapi3/test/info.test.ts
+68 −0 packages/openapi3/test/tsp-openapi3/convert-openapi3-doc.test.ts
+2 −0 packages/spec-api/src/types.ts
+14 −6 packages/spector/src/app/request-processor.ts
+6 −0 packages/tspd/src/cli.ts
+58 −2 packages/tspd/src/ref-doc/emitters/starlight.ts
+9 −1 packages/tspd/src/ref-doc/experimental.ts
+77 −6 packages/tspd/src/ref-doc/extractor.ts
+2 −0 packages/tspd/src/ref-doc/lib.ts
+11 −0 packages/tspd/src/ref-doc/types.ts
+24 −52 packages/typespec-vscode/src/vscode-cmd/create-tsp-project.ts
+433 −518 pnpm-lock.yaml
+1 −0 pnpm-workspace.yaml
+1 −2 website/src/content/current-sidebar.ts
+0 −203 website/src/content/docs/docs/emitters/openapi3/diagnostics.md
+32 −0 website/src/content/docs/docs/emitters/openapi3/reference/diagnostics/duplicate-header.md
+29 −0 website/src/content/docs/docs/emitters/openapi3/reference/diagnostics/inline-cycle.md
+30 −0 website/src/content/docs/docs/emitters/openapi3/reference/diagnostics/invalid-schema.md
+24 −0 website/src/content/docs/docs/emitters/openapi3/reference/diagnostics/invalid-server-variable.md
+36 −0 website/src/content/docs/docs/emitters/openapi3/reference/diagnostics/path-query.md
+13 −0 website/src/content/docs/docs/emitters/openapi3/reference/diagnostics/union-null.md
+24 −0 website/src/content/docs/docs/extending-typespec/linters.md
+3 −3 website/src/content/docs/docs/libraries/http/reference/linter.md
+3 −3 website/src/content/docs/docs/libraries/http/reference/rules/op-reference-container-route.md
+6 −5 website/src/content/docs/docs/libraries/openapi/reference/data-types.md
12 changes: 7 additions & 5 deletions eng/feeds/test/init-templates.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ import {
makeScaffoldingConfig,
scaffoldNewProject,
} from "../node_modules/@typespec/compiler/dist/src/init/scaffold.js";
import { UriTemplateSource } from "../node_modules/@typespec/compiler/dist/src/init/template-source/uri-template-source.js";
const __dirname = import.meta.dirname;
const root = resolve(__dirname, "../");
const testTempRoot = resolve(root, "temp/scaffolded-template-tests");
const snapshotFolder = resolve(root, "__snapshots__");

export const templatesDir = resolvePath(root);
const content = JSON.parse(
await readFile(resolvePath(templatesDir, "azure-scaffolding.json"), "utf-8"),
);
const scaffoldingIndexPath = resolvePath(templatesDir, "azure-scaffolding.json");
const content = JSON.parse(await readFile(scaffoldingIndexPath, "utf-8"));

/** Reads the template files referenced by the templates relative to the scaffolding index. */
const templateSource = new UriTemplateSource(NodeHost, scaffoldingIndexPath);

export const Templates = {
baseUri: templatesDir,
templates: content as Record<string, InitTemplate>,
};

Expand Down Expand Up @@ -86,7 +88,7 @@ describe("Init templates e2e tests", () => {
makeScaffoldingConfig(template, {
name,
directory: targetFolder,
baseUri: Templates.baseUri,
source: templateSource,
parameters,
}),
);
Expand Down
24 changes: 3 additions & 21 deletions eng/scripts/create-linter-rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,18 +192,7 @@ function main(): void {
const packageRoot = resolve(repoRoot, "packages", config.packageDir);
const rulePath = resolve(packageRoot, "src", "rules", `${options.ruleName}.ts`);
const testPath = resolve(packageRoot, "test", "rules", `${options.ruleName}.test.ts`);
const docsPath = resolve(
repoRoot,
"website",
"src",
"content",
"docs",
"docs",
"libraries",
config.docsLibraryDir,
"rules",
`${options.ruleName}.md`,
);
const docsPath = resolve(packageRoot, "src", "rules", `${options.ruleName}.md`);
const linterPath = resolve(packageRoot, "src", "linter.ts");

const fileTargets = [rulePath, testPath, docsPath];
Expand All @@ -219,13 +208,14 @@ function main(): void {
}

const ruleFile = [
'import { createRule } from "@typespec/compiler";',
'import { createRule, fileRef } from "@typespec/compiler";',
"",
`export const ${ruleIdentifier} = createRule({`,
` name: ${toDoubleQuotedString(options.ruleName)},`,
` description: ${toDoubleQuotedString(options.description)},`,
' severity: "warning",',
` url: ${toDoubleQuotedString(`https://azure.github.io/typespec-azure/docs/libraries/${config.docsLibraryDir}/rules/${options.ruleName}`)},`,
` docs: fileRef.fromPackageRoot(${toDoubleQuotedString(`src/rules/${options.ruleName}.md`)}),`,
" messages: {",
' default: "TODO: Add default diagnostic message.",',
" },",
Expand Down Expand Up @@ -287,14 +277,6 @@ function main(): void {
].join("\n");

const docsFile = [
"---",
`title: ${toDoubleQuotedString(options.ruleName)}`,
"---",
"",
'```text title="Full name"',
`${config.packageNpmName}/${options.ruleName}`,
"```",
"",
"TODO: Add a description of what this rule checks and why it matters.",
"",
"#### ❌ Incorrect",
Expand Down
2 changes: 1 addition & 1 deletion packages/typespec-azure-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Available ruleSets:
| [`@azure-tools/typespec-azure-core/no-openapi`](https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/no-openapi) | Azure specs should not be using decorators from @typespec/openapi or @azure-tools/typespec-autorest |
| [`@azure-tools/typespec-azure-core/no-unnamed-union`](https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/no-unnamed-union) | Azure services should not define a union expression but create a declaration. |
| [`@azure-tools/typespec-azure-core/no-header-explode`](https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/no-header-explode) | It is recommended to serialize header parameter without explode: true |
| [`@azure-tools/typespec-azure-core/no-format`](https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/prevent-format) | Azure services should not use the `@format` decorator. |
| [`@azure-tools/typespec-azure-core/no-format`](https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/no-format) | Azure services should not use the `@format` decorator. |
| [`@azure-tools/typespec-azure-core/no-multiple-discriminator`](https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/no-multiple-discriminator) | Classes should have at most one discriminator. |
| [`@azure-tools/typespec-azure-core/no-rest-library-interfaces`](https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/no-rest-library-interfaces) | Resource interfaces from the TypeSpec.Rest.Resource library are incompatible with Azure.Core. |
| [`@azure-tools/typespec-azure-core/no-unknown`](https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/no-unknown) | Azure services must not have properties of type `unknown`. |
Expand Down
2 changes: 1 addition & 1 deletion packages/typespec-azure-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"test:ci": "vitest run --coverage --reporter=junit --reporter=default",
"lint": "oxlint . --deny-warnings",
"lint:fix": "oxlint . --fix",
"regen-docs": "tspd doc . --enable-experimental --llmstxt --output-dir ../../website/src/content/docs/docs/libraries/azure-core/reference"
"regen-docs": "tspd doc . --enable-experimental --llmstxt --rules-dir ../rules --output-dir ../../website/src/content/docs/docs/libraries/azure-core/reference"
},
"files": [
"lib/**/*.tsp",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "auth-required"
---

```text title="Full name"
@azure-tools/typespec-azure-core/auth-required
```

Ensure Azure services define their authentication requirements. See https://azure.github.io/typespec-azure/docs/reference/azure-style-guide#security-definitions

#### ❌ Incorrect
Expand Down
3 changes: 2 additions & 1 deletion packages/typespec-azure-core/src/rules/auth-required.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Namespace, createRule, getService } from "@typespec/compiler";
import { Namespace, createRule, fileRef, getService } from "@typespec/compiler";
import { getAuthentication } from "@typespec/http";

export const authRequiredRule = createRule({
name: "auth-required",
docs: fileRef.fromPackageRoot("src/rules/auth-required.md"),
description: "Enforce service authentication.",
severity: "warning",
url: "https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/auth-required",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "bad-record-type"
---

```text title="Full name"
@azure-tools/typespec-azure-core/bad-record-type
```

Use of `Record<X>` should be limited in Azure services.

1. It is recommended to use `Record<string>` instead of `Record<unknown>`
Expand Down
2 changes: 2 additions & 0 deletions packages/typespec-azure-core/src/rules/bad-record-type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ModelProperty,
Type,
createRule,
fileRef,
paramMessage,
} from "@typespec/compiler";

Expand Down Expand Up @@ -76,6 +77,7 @@ function validatePropertyRecordType(

export const badRecordTypeRule = createRule({
name: "bad-record-type",
docs: fileRef.fromPackageRoot("src/rules/bad-record-type.md"),
description: "Identify bad record definitions.",
severity: "warning",
url: "https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/bad-record-type",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "byos"
---

```text title="Full name"
@azure-tools/typespec-azure-core/byos
```

Operations that upload binary data (using content types like `application/octet-stream` or `multipart/form-data`) should use the Bring Your Own Storage (BYOS) pattern recommended for Azure Services.

See the [Azure REST API Guidelines - BYOS](https://github.com/microsoft/api-guidelines/blob/vNext/azure/Guidelines.md#bring-your-own-storage-byos) for more details.
Expand Down
2 changes: 2 additions & 0 deletions packages/typespec-azure-core/src/rules/byos.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
Operation,
createRule,
fileRef,
ignoreDiagnostics,
isTemplateInstance,
paramMessage,
Expand All @@ -10,6 +11,7 @@ import { getHttpOperation } from "@typespec/http";
const binaryContentTypes = new Set(["application/octet-stream", "multipart/form-data"]);
export const byosRule = createRule({
name: "byos",
docs: fileRef.fromPackageRoot("src/rules/byos.md"),
description: "Use the BYOS pattern recommended for Azure Services.",
severity: "warning",
url: "https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/byos",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "casing-style"
---

```text title="Full name"
@azure-tools/typespec-azure-core/casing-style
```

Validate names follow the [TypeSpec Style guide](https://typespec.io/docs/handbook/style-guide)

#### ❌ Incorrect
Expand Down
2 changes: 2 additions & 0 deletions packages/typespec-azure-core/src/rules/casing-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
Namespace,
Operation,
createRule,
fileRef,
isTemplateDeclarationOrInstance,
paramMessage,
} from "@typespec/compiler";
Expand All @@ -13,6 +14,7 @@ import { isCamelCaseNoAcronyms, isPascalCaseWithAcceptedAcronyms } from "./utils
const acceptedAzureAcronyms = ["AI", "VM", "OS", "IP", "CPU", "GPU", "LRO"];
export const casingRule = createRule({
name: "casing-style",
docs: fileRef.fromPackageRoot("src/rules/casing-style.md"),
description: "Ensure proper casing style.",
severity: "warning",
url: "https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/casing-style",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "composition-over-inheritance"
---

```text title="Full name"
@azure-tools/typespec-azure-core/composition-over-inheritance
```

Models that extend a base model without a discriminator should use composition (`...` spread or `model is`) instead of inheritance (`extends`). If polymorphism is intended, add the `@discriminator` decorator on the base model.

#### ❌ Incorrect
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
createRule,
fileRef,
getDiscriminator,
getTypeName,
isTemplateInstance,
Expand All @@ -9,6 +10,7 @@ import { SyntaxKind } from "@typespec/compiler/ast";

export const compositionOverInheritanceRule = createRule({
name: "composition-over-inheritance",
docs: fileRef.fromPackageRoot("src/rules/composition-over-inheritance.md"),
description:
"Check that if a model is used in an operation and has derived models that it has a discriminator or recommend to use composition via spread or `is`.",
severity: "warning",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "documentation-required"
---

```text title="Full name"
@azure-tools/typespec-azure-core/documentation-required
```

Enums, models, operations, and their members/properties should have documentation. Use doc comments (`/** */`) to provide descriptions.

#### ❌ Incorrect
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "friendly-name"
---

```text title="Full name"
@azure-tools/typespec-azure-core/friendly-name
```

Ensures that `@friendlyName` is used as intended. The `@friendlyName` decorator should only be applied to template declarations and should reference template parameter properties in the friendly name string.

#### ❌ Incorrect
Expand Down
2 changes: 2 additions & 0 deletions packages/typespec-azure-core/src/rules/friendly-name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DecoratorApplication,
Enum,
EnumMember,
fileRef,
Interface,
isTemplateInstance,
LinterRuleContext,
Expand All @@ -22,6 +23,7 @@ import { SyntaxKind } from "@typespec/compiler/ast";

export const friendlyNameRule = createRule({
name: "friendly-name",
docs: fileRef.fromPackageRoot("src/rules/friendly-name.md"),
description: "Ensures that @friendlyName is used as intended.",
severity: "warning",
url: "https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/friendly-name",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "key-visibility-required"
---

```text title="Full name"
@azure-tools/typespec-azure-core/key-visibility-required
```

Key properties need to have an explicit Lifecycle visibility setting. Use the `@visibility` decorator to specify the appropriate visibility for key properties. Without explicit visibility, the key property uses default visibility which may not match the intended behavior.

#### ❌ Incorrect
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "known-encoding"
---

```text title="Full name"
@azure-tools/typespec-azure-core/known-encoding
```

Check that `@encode` uses a supported encoding for Azure services.

Known supported encodings:
Expand Down
10 changes: 9 additions & 1 deletion packages/typespec-azure-core/src/rules/known-encoding.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { ModelProperty, Scalar, createRule, getEncode, paramMessage } from "@typespec/compiler";
import {
ModelProperty,
Scalar,
createRule,
fileRef,
getEncode,
paramMessage,
} from "@typespec/compiler";

const knownEncodings = new Set([
// utcDateTime and offsetDateTime
Expand All @@ -14,6 +21,7 @@ const knownEncodings = new Set([
]);
export const knownEncodingRule = createRule({
name: "known-encoding",
docs: fileRef.fromPackageRoot("src/rules/known-encoding.md"),
description: "Check for supported encodings.",
severity: "warning",
url: "https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/known-encoding",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
---
title: "long-running-polling-operation-required"
---

```text title="Full name"
@azure-tools/typespec-azure-core/long-running-polling-operation-required
```

Long-running operations that return an `Operation-Location` header should have a linked polling operation. Use the `@pollingOperation` decorator to link a status polling operation.

#### ❌ Incorrect
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Operation, Program, Type, createRule } from "@typespec/compiler";
import { Operation, Program, Type, createRule, fileRef } from "@typespec/compiler";
import { getHeaderFieldName, isHeader } from "@typespec/http";
import { getOperationLink } from "../decorators/operation-link.js";
import {
Expand All @@ -22,6 +22,7 @@ function hasOperationLocation(program: Program, entity: Type): boolean {

export const longRunningOperationsRequirePollingOperation = createRule({
name: "long-running-polling-operation-required",
docs: fileRef.fromPackageRoot("src/rules/long-running-polling-operation-required.md"),
description: "Long-running operations should have a linked polling operation.",
severity: "warning",
url: "https://azure.github.io/typespec-azure/docs/libraries/azure-core/rules/long-running-polling-operation-required",
Expand Down
Loading
Loading