Format multi line strings (#3422)
fix #1016 Format multi lines string ``` @doc( """ multi line do ${"abc"} """ ) @doc(""" def """) model Foo {} alias T = """ abc def ${"abc"} ghi """; ``` formats to ``` @doc(""" multi line do ${"abc"} """) @doc(""" def """) model Foo {} alias T = """ abc def ${"abc"} ghi """; ```
This commit is contained in:
Родитель
7912e8c9c7
Коммит
dd61517865
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
|
||||||
|
changeKind: feature
|
||||||
|
packages:
|
||||||
|
- "@typespec/compiler"
|
||||||
|
---
|
||||||
|
|
||||||
|
Formatter: Indent or dedent multiline strings to the current indentation
|
|
@ -244,13 +244,13 @@ and can contain markdown formatting.
|
||||||
|
|
||||||
```typespec
|
```typespec
|
||||||
@doc("""
|
@doc("""
|
||||||
Get status info for the service.
|
Get status info for the service.
|
||||||
The status includes the current version of the service.
|
The status includes the current version of the service.
|
||||||
The status value may be one of:
|
The status value may be one of:
|
||||||
- `ok`: the service is operating normally
|
- `ok`: the service is operating normally
|
||||||
- `degraded`: the service is operating in a degraded state
|
- `degraded`: the service is operating in a degraded state
|
||||||
- `down`: the service is not operating
|
- `down`: the service is not operating
|
||||||
""")
|
""")
|
||||||
@tag("Status")
|
@tag("Status")
|
||||||
@route("/status")
|
@route("/status")
|
||||||
@get
|
@get
|
||||||
|
|
|
@ -21,10 +21,10 @@ Multi-line string literals are denoted using three double quotes `"""`.
|
||||||
|
|
||||||
```typespec
|
```typespec
|
||||||
alias Str = """
|
alias Str = """
|
||||||
This is a multi line string
|
This is a multi line string
|
||||||
- opt 1
|
- opt 1
|
||||||
- opt 2
|
- opt 2
|
||||||
""";
|
""";
|
||||||
```
|
```
|
||||||
|
|
||||||
- The opening `"""` must be followed by a new line.
|
- The opening `"""` must be followed by a new line.
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import type { AstPath, Doc, Printer } from "prettier";
|
import type { AstPath, Doc, Printer } from "prettier";
|
||||||
import { builders } from "prettier/doc";
|
import { builders } from "prettier/doc";
|
||||||
import { isIdentifierContinue, isIdentifierStart, utf16CodeUnits } from "../../core/charcode.js";
|
import {
|
||||||
|
CharCode,
|
||||||
|
isIdentifierContinue,
|
||||||
|
isIdentifierStart,
|
||||||
|
utf16CodeUnits,
|
||||||
|
} from "../../core/charcode.js";
|
||||||
import { compilerAssert } from "../../core/diagnostics.js";
|
import { compilerAssert } from "../../core/diagnostics.js";
|
||||||
import { Keywords } from "../../core/scanner.js";
|
import { Keywords } from "../../core/scanner.js";
|
||||||
import {
|
import {
|
||||||
|
@ -86,7 +91,19 @@ import { commentHandler } from "./comment-handler.js";
|
||||||
import { needsParens } from "./needs-parens.js";
|
import { needsParens } from "./needs-parens.js";
|
||||||
import { DecorableNode, PrettierChildPrint, TypeSpecPrettierOptions } from "./types.js";
|
import { DecorableNode, PrettierChildPrint, TypeSpecPrettierOptions } from "./types.js";
|
||||||
import { util } from "./util.js";
|
import { util } from "./util.js";
|
||||||
const { align, breakParent, group, hardline, ifBreak, indent, join, line, softline } = builders;
|
const {
|
||||||
|
align,
|
||||||
|
breakParent,
|
||||||
|
group,
|
||||||
|
hardline,
|
||||||
|
ifBreak,
|
||||||
|
indent,
|
||||||
|
join,
|
||||||
|
line,
|
||||||
|
softline,
|
||||||
|
literalline,
|
||||||
|
markAsRoot,
|
||||||
|
} = builders;
|
||||||
|
|
||||||
const { isNextLineEmpty } = util as any;
|
const { isNextLineEmpty } = util as any;
|
||||||
|
|
||||||
|
@ -689,7 +706,8 @@ function printCallOrDecoratorArgs(
|
||||||
const shouldHug =
|
const shouldHug =
|
||||||
node.arguments.length === 1 &&
|
node.arguments.length === 1 &&
|
||||||
(node.arguments[0].kind === SyntaxKind.ModelExpression ||
|
(node.arguments[0].kind === SyntaxKind.ModelExpression ||
|
||||||
node.arguments[0].kind === SyntaxKind.StringLiteral);
|
node.arguments[0].kind === SyntaxKind.StringLiteral ||
|
||||||
|
node.arguments[0].kind === SyntaxKind.StringTemplateExpression);
|
||||||
|
|
||||||
if (shouldHug) {
|
if (shouldHug) {
|
||||||
return [
|
return [
|
||||||
|
@ -1637,7 +1655,28 @@ function printStringLiteral(
|
||||||
options: TypeSpecPrettierOptions
|
options: TypeSpecPrettierOptions
|
||||||
): Doc {
|
): Doc {
|
||||||
const node = path.node;
|
const node = path.node;
|
||||||
return getRawText(node, options);
|
const multiline = isMultiline(node, options);
|
||||||
|
|
||||||
|
const raw = getRawText(node, options);
|
||||||
|
if (multiline) {
|
||||||
|
const lines = splitLines(raw.slice(3));
|
||||||
|
const whitespaceIndent = lines[lines.length - 1].length - 3;
|
||||||
|
const newLines = trimMultilineString(lines, whitespaceIndent);
|
||||||
|
return [`"""`, indent(markAsRoot(newLines))];
|
||||||
|
} else {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMultiline(
|
||||||
|
node: StringLiteralNode | StringTemplateExpressionNode,
|
||||||
|
options: TypeSpecPrettierOptions
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
options.originalText[node.pos] &&
|
||||||
|
options.originalText[node.pos + 1] === `"` &&
|
||||||
|
options.originalText[node.pos + 2] === `"`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function printNumberLiteral(
|
function printNumberLiteral(
|
||||||
|
@ -1871,14 +1910,79 @@ export function printStringTemplateExpression(
|
||||||
print: PrettierChildPrint
|
print: PrettierChildPrint
|
||||||
) {
|
) {
|
||||||
const node = path.node;
|
const node = path.node;
|
||||||
const content = [
|
const multiline = isMultiline(node, options);
|
||||||
getRawText(node.head, options),
|
const rawHead = getRawText(node.head, options);
|
||||||
path.map((span: AstPath<StringTemplateSpanNode>) => {
|
if (multiline) {
|
||||||
const expression = span.call(print, "expression");
|
const lastSpan = node.spans[node.spans.length - 1];
|
||||||
return [expression, getRawText(span.node.literal, options)];
|
const lastLines = splitLines(getRawText(lastSpan.literal, options));
|
||||||
}, "spans"),
|
const whitespaceIndent = lastLines[lastLines.length - 1].length - 3;
|
||||||
];
|
const content = [
|
||||||
return content;
|
trimMultilineString(splitLines(rawHead.slice(3)), whitespaceIndent),
|
||||||
|
path.map((span: AstPath<StringTemplateSpanNode>) => {
|
||||||
|
const expression = span.call(print, "expression");
|
||||||
|
const spanRawText = getRawText(span.node.literal, options);
|
||||||
|
const spanLines = splitLines(spanRawText);
|
||||||
|
return [
|
||||||
|
expression,
|
||||||
|
spanLines[0],
|
||||||
|
literalline,
|
||||||
|
trimMultilineString(spanLines.slice(1), whitespaceIndent),
|
||||||
|
];
|
||||||
|
}, "spans"),
|
||||||
|
];
|
||||||
|
|
||||||
|
return [`"""`, indent(markAsRoot([content]))];
|
||||||
|
} else {
|
||||||
|
const content = [
|
||||||
|
rawHead,
|
||||||
|
path.map((span: AstPath<StringTemplateSpanNode>) => {
|
||||||
|
const expression = span.call(print, "expression");
|
||||||
|
return [expression, getRawText(span.node.literal, options)];
|
||||||
|
}, "spans"),
|
||||||
|
];
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitLines(text: string): string[] {
|
||||||
|
const lines = [];
|
||||||
|
let start = 0;
|
||||||
|
let pos = 0;
|
||||||
|
|
||||||
|
while (pos < text.length) {
|
||||||
|
const ch = text.charCodeAt(pos);
|
||||||
|
switch (ch) {
|
||||||
|
case CharCode.CarriageReturn:
|
||||||
|
if (text.charCodeAt(pos + 1) === CharCode.LineFeed) {
|
||||||
|
lines.push(text.slice(start, pos));
|
||||||
|
start = pos;
|
||||||
|
pos++;
|
||||||
|
} else {
|
||||||
|
lines.push(text.slice(start, pos));
|
||||||
|
start = pos;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CharCode.LineFeed:
|
||||||
|
lines.push(text.slice(start, pos));
|
||||||
|
start = pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.push(text.slice(start));
|
||||||
|
return lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
function trimMultilineString(lines: string[], whitespaceIndent: number): Doc[] {
|
||||||
|
const newLines = [];
|
||||||
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
newLines.push(lines[i].slice(whitespaceIndent));
|
||||||
|
if (i < lines.length - 1) {
|
||||||
|
newLines.push(literalline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
function printItemList<T extends Node>(
|
function printItemList<T extends Node>(
|
||||||
|
|
|
@ -1807,7 +1807,7 @@ namespace Foo {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("string literals", () => {
|
describe("single line string literals", () => {
|
||||||
it("format single line string literal", async () => {
|
it("format single line string literal", async () => {
|
||||||
await assertFormat({
|
await assertFormat({
|
||||||
code: `
|
code: `
|
||||||
|
@ -1835,14 +1835,37 @@ model Foo {}
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("format multi line string literal", async () => {
|
describe("multi line string literals", () => {
|
||||||
|
it("keeps trailing whitespaces", async () => {
|
||||||
await assertFormat({
|
await assertFormat({
|
||||||
code: `
|
code: `
|
||||||
@doc( """
|
@doc( """
|
||||||
|
3 whitespaces
|
||||||
|
|
||||||
|
and blank line above
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
model Foo {}
|
||||||
|
`,
|
||||||
|
expected: `
|
||||||
|
@doc("""
|
||||||
|
3 whitespaces
|
||||||
|
|
||||||
this is a doc.
|
and blank line above
|
||||||
that
|
""")
|
||||||
|
model Foo {}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps indent relative to closing quotes", async () => {
|
||||||
|
await assertFormat({
|
||||||
|
code: `
|
||||||
|
@doc( """
|
||||||
|
this is a doc.
|
||||||
|
that
|
||||||
span
|
span
|
||||||
multiple lines.
|
multiple lines.
|
||||||
"""
|
"""
|
||||||
|
@ -1851,12 +1874,31 @@ model Foo {}
|
||||||
`,
|
`,
|
||||||
expected: `
|
expected: `
|
||||||
@doc("""
|
@doc("""
|
||||||
|
this is a doc.
|
||||||
this is a doc.
|
that
|
||||||
that
|
span
|
||||||
span
|
multiple lines.
|
||||||
multiple lines.
|
""")
|
||||||
""")
|
model Foo {}
|
||||||
|
`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps escaped charaters", async () => {
|
||||||
|
await assertFormat({
|
||||||
|
code: `
|
||||||
|
@doc( """
|
||||||
|
with \\n
|
||||||
|
and \\t
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
model Foo {}
|
||||||
|
`,
|
||||||
|
expected: `
|
||||||
|
@doc("""
|
||||||
|
with \\n
|
||||||
|
and \\t
|
||||||
|
""")
|
||||||
model Foo {}
|
model Foo {}
|
||||||
`,
|
`,
|
||||||
});
|
});
|
||||||
|
@ -2847,11 +2889,11 @@ alias T = "foo \${{
|
||||||
await assertFormat({
|
await assertFormat({
|
||||||
code: `
|
code: `
|
||||||
alias T = """
|
alias T = """
|
||||||
This \${ "one" } goes over
|
This \${ "one" } goes over
|
||||||
multiple
|
multiple
|
||||||
\${ "two" }
|
\${ "two" }
|
||||||
lines
|
lines
|
||||||
""";`,
|
""";`,
|
||||||
expected: `
|
expected: `
|
||||||
alias T = """
|
alias T = """
|
||||||
This \${"one"} goes over
|
This \${"one"} goes over
|
||||||
|
|
|
@ -80,9 +80,9 @@ model Kiosk {
|
||||||
}
|
}
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
Describes a digital sign.
|
Describes a digital sign.
|
||||||
Signs can include text, images, or both.
|
Signs can include text, images, or both.
|
||||||
""")
|
""")
|
||||||
model Sign {
|
model Sign {
|
||||||
@doc("unique id")
|
@doc("unique id")
|
||||||
id?: int32; // Output only.
|
id?: int32; // Output only.
|
||||||
|
|
|
@ -15,12 +15,12 @@ model Timestamp {
|
||||||
}
|
}
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
An object that represents a latitude/longitude pair. This is expressed as a
|
An object that represents a latitude/longitude pair. This is expressed as a
|
||||||
pair of doubles to represent degrees latitude and degrees longitude. Unless
|
pair of doubles to represent degrees latitude and degrees longitude. Unless
|
||||||
specified otherwise, this must conform to the
|
specified otherwise, this must conform to the
|
||||||
<a href="http://www.unoosa.org/pdf/icg/2012/template/WGS_84.pdf">WGS84
|
<a href="http://www.unoosa.org/pdf/icg/2012/template/WGS_84.pdf">WGS84
|
||||||
standard</a>. Values must be within normalized ranges.
|
standard</a>. Values must be within normalized ranges.
|
||||||
""")
|
""")
|
||||||
model LatLng {
|
model LatLng {
|
||||||
// The latitude in degrees. It must be in the range [-90.0, +90.0].
|
// The latitude in degrees. It must be in the range [-90.0, +90.0].
|
||||||
latitude: float64;
|
latitude: float64;
|
||||||
|
|
|
@ -14,16 +14,16 @@ using TypeSpec.Http;
|
||||||
namespace GrpcLibrarySample;
|
namespace GrpcLibrarySample;
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
This API represents a simple digital library. It lets you manage Shelf
|
This API represents a simple digital library. It lets you manage Shelf
|
||||||
resources and Book resources in the library. It defines the following
|
resources and Book resources in the library. It defines the following
|
||||||
resource model:
|
resource model:
|
||||||
|
|
||||||
- The API has a collection of [Shelf][google.example.library.v1.Shelf]
|
- The API has a collection of [Shelf][google.example.library.v1.Shelf]
|
||||||
resources, named `shelves/*`
|
resources, named `shelves/*`
|
||||||
|
|
||||||
- Each Shelf has a collection of [Book][google.example.library.v1.Book]
|
- Each Shelf has a collection of [Book][google.example.library.v1.Book]
|
||||||
resources, named `shelves/*/books/*`
|
resources, named `shelves/*/books/*`
|
||||||
""")
|
""")
|
||||||
@route("/v1")
|
@route("/v1")
|
||||||
@tag("LibraryService")
|
@tag("LibraryService")
|
||||||
namespace LibraryService {
|
namespace LibraryService {
|
||||||
|
@ -37,9 +37,9 @@ namespace LibraryService {
|
||||||
op getShelf(...GetShelfRequest): Shelf | RpcStatus;
|
op getShelf(...GetShelfRequest): Shelf | RpcStatus;
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
Lists shelves. The order is unspecified but deterministic. Newly created
|
Lists shelves. The order is unspecified but deterministic. Newly created
|
||||||
shelves will not necessarily be added to the end of this list.
|
shelves will not necessarily be added to the end of this list.
|
||||||
""")
|
""")
|
||||||
@route("shelves")
|
@route("shelves")
|
||||||
op listShelves(...ListRequestBase): ListShelvesResponse | RpcStatus;
|
op listShelves(...ListRequestBase): ListShelvesResponse | RpcStatus;
|
||||||
|
|
||||||
|
@ -49,13 +49,13 @@ shelves will not necessarily be added to the end of this list.
|
||||||
op deleteShelf(...DeleteShelfRequest): void | RpcStatus;
|
op deleteShelf(...DeleteShelfRequest): void | RpcStatus;
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
Merges two shelves by adding all books from the shelf named
|
Merges two shelves by adding all books from the shelf named
|
||||||
`other_shelf_name` to shelf `name`, and deletes
|
`other_shelf_name` to shelf `name`, and deletes
|
||||||
`other_shelf_name`. Returns the updated shelf.
|
`other_shelf_name`. Returns the updated shelf.
|
||||||
The book ids of the moved books may not be the same as the original books.
|
The book ids of the moved books may not be the same as the original books.
|
||||||
Returns NOT_FOUND if either shelf does not exist.
|
Returns NOT_FOUND if either shelf does not exist.
|
||||||
This call is a no-op if the specified shelves are the same.
|
This call is a no-op if the specified shelves are the same.
|
||||||
""")
|
""")
|
||||||
@route("shelves/{name}:merge")
|
@route("shelves/{name}:merge")
|
||||||
@post
|
@post
|
||||||
op mergeShelves(...MergeShelvesRequest): Shelf | RpcStatus;
|
op mergeShelves(...MergeShelvesRequest): Shelf | RpcStatus;
|
||||||
|
@ -70,10 +70,10 @@ This call is a no-op if the specified shelves are the same.
|
||||||
op getBook(...GetBookRequest): Book | RpcStatus;
|
op getBook(...GetBookRequest): Book | RpcStatus;
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
Lists books in a shelf. The order is unspecified but deterministic. Newly
|
Lists books in a shelf. The order is unspecified but deterministic. Newly
|
||||||
created books will not necessarily be added to the end of this list.
|
created books will not necessarily be added to the end of this list.
|
||||||
Returns NOT_FOUND if the shelf does not exist.
|
Returns NOT_FOUND if the shelf does not exist.
|
||||||
""")
|
""")
|
||||||
@route("shelves/{name}/books")
|
@route("shelves/{name}/books")
|
||||||
op listBooks(...ListBooksRequest): ListBooksResponse | RpcStatus;
|
op listBooks(...ListBooksRequest): ListBooksResponse | RpcStatus;
|
||||||
|
|
||||||
|
@ -84,19 +84,19 @@ Returns NOT_FOUND if the shelf does not exist.
|
||||||
}
|
}
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
The name of a book.
|
The name of a book.
|
||||||
Book names have the form `shelves/{shelf_id}/books/{book_id}`
|
Book names have the form `shelves/{shelf_id}/books/{book_id}`
|
||||||
""")
|
""")
|
||||||
@pattern("shelves/\\w+/books/\\w+")
|
@pattern("shelves/\\w+/books/\\w+")
|
||||||
scalar book_name extends string;
|
scalar book_name extends string;
|
||||||
|
|
||||||
@doc("A single book in the library.")
|
@doc("A single book in the library.")
|
||||||
model Book {
|
model Book {
|
||||||
@doc("""
|
@doc("""
|
||||||
The resource name of the book.
|
The resource name of the book.
|
||||||
Book names have the form `shelves/{shelf_id}/books/{book_id}`.
|
Book names have the form `shelves/{shelf_id}/books/{book_id}`.
|
||||||
The name is ignored when creating a book.
|
The name is ignored when creating a book.
|
||||||
""")
|
""")
|
||||||
name: book_name;
|
name: book_name;
|
||||||
|
|
||||||
@doc("The name of the book author.")
|
@doc("The name of the book author.")
|
||||||
|
@ -110,19 +110,19 @@ The name is ignored when creating a book.
|
||||||
}
|
}
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
The name of a shelf.
|
The name of a shelf.
|
||||||
Shelf names have the form `shelves/{shelf_id}`.
|
Shelf names have the form `shelves/{shelf_id}`.
|
||||||
""")
|
""")
|
||||||
@pattern("shelves/\\w+")
|
@pattern("shelves/\\w+")
|
||||||
scalar shelf_name extends string;
|
scalar shelf_name extends string;
|
||||||
|
|
||||||
@doc("A Shelf contains a collection of books with a theme.")
|
@doc("A Shelf contains a collection of books with a theme.")
|
||||||
model Shelf {
|
model Shelf {
|
||||||
@doc("""
|
@doc("""
|
||||||
The resource name of the shelf.
|
The resource name of the shelf.
|
||||||
Shelf names have the form `shelves/{shelf_id}`.
|
Shelf names have the form `shelves/{shelf_id}`.
|
||||||
The name is ignored when creating a shelf.
|
The name is ignored when creating a shelf.
|
||||||
""")
|
""")
|
||||||
name: shelf_name;
|
name: shelf_name;
|
||||||
|
|
||||||
@doc("The theme of the shelf")
|
@doc("The theme of the shelf")
|
||||||
|
@ -159,9 +159,9 @@ model DeleteShelfRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
Describes the shelf being removed (other_shelf_name) and updated
|
Describes the shelf being removed (other_shelf_name) and updated
|
||||||
(name) in this merge
|
(name) in this merge
|
||||||
""")
|
""")
|
||||||
model MergeShelvesRequest {
|
model MergeShelvesRequest {
|
||||||
@doc("The name of the shelf we're adding books to.")
|
@doc("The name of the shelf we're adding books to.")
|
||||||
@path
|
@path
|
||||||
|
@ -229,9 +229,9 @@ model DeleteBookRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
Describes what book to move (name) and what shelf we're moving it
|
Describes what book to move (name) and what shelf we're moving it
|
||||||
to (other_shelf_name).
|
to (other_shelf_name).
|
||||||
""")
|
""")
|
||||||
model MoveBookRequest {
|
model MoveBookRequest {
|
||||||
@doc("The name of the book to move.")
|
@doc("The name of the book to move.")
|
||||||
name: book_name;
|
name: book_name;
|
||||||
|
@ -246,30 +246,30 @@ model MoveBookRequest {
|
||||||
|
|
||||||
model ListRequestBase {
|
model ListRequestBase {
|
||||||
@doc("""
|
@doc("""
|
||||||
Requested page size. Server may return fewer shelves than requested.
|
Requested page size. Server may return fewer shelves than requested.
|
||||||
If unspecified, server will pick an appropriate default.
|
If unspecified, server will pick an appropriate default.
|
||||||
""")
|
""")
|
||||||
@query
|
@query
|
||||||
page_size?: int32;
|
page_size?: int32;
|
||||||
|
|
||||||
@doc("""
|
@doc("""
|
||||||
A token identifying a page of results the server should return.
|
A token identifying a page of results the server should return.
|
||||||
Typically, this is the value of
|
Typically, this is the value of
|
||||||
[ListShelvesResponse.next_page_token][google.example.library.v1.ListShelvesResponse.next_page_token]
|
[ListShelvesResponse.next_page_token][google.example.library.v1.ListShelvesResponse.next_page_token]
|
||||||
returned from the previous call to `ListShelves` method.
|
returned from the previous call to `ListShelves` method.
|
||||||
""")
|
""")
|
||||||
@query
|
@query
|
||||||
page_token?: string;
|
page_token?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
model ListResponseBase {
|
model ListResponseBase {
|
||||||
@doc("""
|
@doc("""
|
||||||
A token to retrieve next page of results.
|
A token to retrieve next page of results.
|
||||||
Pass this value in the
|
Pass this value in the
|
||||||
[ListShelvesRequest.page_token][google.example.library.v1.ListShelvesRequest.page_token]
|
[ListShelvesRequest.page_token][google.example.library.v1.ListShelvesRequest.page_token]
|
||||||
field in the subsequent call to `ListShelves` method to retrieve the next
|
field in the subsequent call to `ListShelves` method to retrieve the next
|
||||||
page of results.
|
page of results.
|
||||||
""")
|
""")
|
||||||
next_page_token?: string;
|
next_page_token?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@ alias myConst = "foobar";
|
||||||
model Person {
|
model Person {
|
||||||
simple: "Simple ${123} end";
|
simple: "Simple ${123} end";
|
||||||
multiline: """
|
multiline: """
|
||||||
Multi
|
Multi
|
||||||
${123}
|
${123}
|
||||||
${true}
|
${true}
|
||||||
line
|
line
|
||||||
""";
|
""";
|
||||||
ref: "Ref this alias ${myConst} end";
|
ref: "Ref this alias ${myConst} end";
|
||||||
template: Template<"custom">;
|
template: Template<"custom">;
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,13 +244,13 @@ and can contain markdown formatting.
|
||||||
|
|
||||||
```typespec
|
```typespec
|
||||||
@doc("""
|
@doc("""
|
||||||
Get status info for the service.
|
Get status info for the service.
|
||||||
The status includes the current version of the service.
|
The status includes the current version of the service.
|
||||||
The status value may be one of:
|
The status value may be one of:
|
||||||
- `ok`: the service is operating normally
|
- `ok`: the service is operating normally
|
||||||
- `degraded`: the service is operating in a degraded state
|
- `degraded`: the service is operating in a degraded state
|
||||||
- `down`: the service is not operating
|
- `down`: the service is not operating
|
||||||
""")
|
""")
|
||||||
@tag("Status")
|
@tag("Status")
|
||||||
@route("/status")
|
@route("/status")
|
||||||
@get
|
@get
|
||||||
|
|
|
@ -21,10 +21,10 @@ Multi-line string literals are denoted using three double quotes `"""`.
|
||||||
|
|
||||||
```typespec
|
```typespec
|
||||||
alias Str = """
|
alias Str = """
|
||||||
This is a multi line string
|
This is a multi line string
|
||||||
- opt 1
|
- opt 1
|
||||||
- opt 2
|
- opt 2
|
||||||
""";
|
""";
|
||||||
```
|
```
|
||||||
|
|
||||||
- The opening `"""` must be followed by a new line.
|
- The opening `"""` must be followed by a new line.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче