Skip to content
Open
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,7 @@
---
changeKind: fix
packages:
- "@typespec/compiler"
---

Keep the `is`/`extends` keyword on the declaration line when the base is a template reference with multiple arguments. The template argument list now controls the line breaking instead of the keyword being pushed onto its own indented line.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
changeKind: internal
packages:
- "@typespec/http-client-java"
---

Reformat a test spec affected by the compiler formatter change keeping `is`/`extends` inline for multi-argument template references (whitespace only, no semantic change).
40 changes: 31 additions & 9 deletions packages/compiler/src/formatter/print/printer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1043,17 +1043,40 @@ export function printArrayLiteral(
]);
}

// When the base is a multi-argument template, its argument list breaks on its
// own, so keep `is`/`extends` inline instead of breaking the keyword too (#11009).
function printHeritageClause<T extends Node>(
path: AstPath<T>,
print: PrettierChildPrint,
keyword: string,
propertyName: keyof T,
): Doc {
const ref = path.node[propertyName] as Node | undefined;
if (!ref) {
return "";
}
const printed = [`${keyword} `, path.call(print, propertyName as any)];
if (isMultiArgTemplateReference(ref)) {
return [" ", printed];
}
return group(indent([ifBreak(line, " "), printed]));
}

function isMultiArgTemplateReference(node: Node): boolean {
return (
node.kind === SyntaxKind.TypeReference && (node as TypeReferenceNode).arguments.length >= 2
);
}

export function printModelStatement(
path: AstPath<ModelStatementNode>,
options: TypeSpecPrettierOptions,
print: PrettierChildPrint,
) {
const node = path.node;
const id = path.call(print, "id");
const heritage = node.extends
? [ifBreak(line, " "), "extends ", path.call(print, "extends")]
: "";
const isBase = node.is ? [ifBreak(line, " "), "is ", path.call(print, "is")] : "";
const heritage = printHeritageClause(path, print, "extends", "extends");
const isBase = printHeritageClause(path, print, "is", "is");
const generic = printTemplateParameters(path, options, print, "templateParameters");
const nodeHasComments = hasComments(node, CommentCheckFlags.Dangling);
const shouldPrintBody = nodeHasComments || !(node.properties.length === 0 && node.is);
Expand All @@ -1064,7 +1087,8 @@ export function printModelStatement(
"model ",
id,
generic,
group(indent(["", heritage, isBase])),
heritage,
isBase,
body,
];
}
Expand Down Expand Up @@ -1240,9 +1264,7 @@ function printScalarStatement(
const id = path.call(print, "id");
const template = printTemplateParameters(path, options, print, "templateParameters");

const heritage = node.extends
? [ifBreak(line, " "), "extends ", path.call(print, "extends")]
: "";
const heritage = printHeritageClause(path, print, "extends", "extends");
const nodeHasComments = hasComments(node, CommentCheckFlags.Dangling);
const shouldPrintBody = nodeHasComments || !(node.members.length === 0);

Expand All @@ -1253,7 +1275,7 @@ function printScalarStatement(
"scalar ",
id,
template,
group(indent(["", heritage])),
heritage,
members,
];
}
Expand Down
45 changes: 45 additions & 0 deletions packages/compiler/test/formatter/formatter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,21 @@ model Foo extends SuperExtremeAndVeryVeryVeryVeryVeryVeryLongModelThatWillBeTo
expected: `
model Foo
extends SuperExtremeAndVeryVeryVeryVeryVeryVeryLongModelThatWillBeTooLong {}
`,
});
});

it("keeps extends inline and breaks the template arguments when too long", async () => {
await assertFormat({
code: `
model Foo extends Base<FirstArgumentTypeName, SecondArgumentTypeName, ThirdArgumentTypeName> {}
`,
expected: `
model Foo extends Base<
FirstArgumentTypeName,
SecondArgumentTypeName,
ThirdArgumentTypeName
> {}
`,
});
});
Expand Down Expand Up @@ -255,6 +270,21 @@ model Foo is SuperExtremeAndVeryVeryVeryVeryVeryVeryLongLongLongModelThatWillB
expected: `
model Foo
is SuperExtremeAndVeryVeryVeryVeryVeryVeryLongLongLongModelThatWillBeTooLong;
`,
});
});

it("keeps is inline and breaks the template arguments when too long", async () => {
await assertFormat({
code: `
model Foo is Base<FirstArgumentTypeName, SecondArgumentTypeName, ThirdArgumentTypeName>;
`,
expected: `
model Foo is Base<
FirstArgumentTypeName,
SecondArgumentTypeName,
ThirdArgumentTypeName
>;
`,
});
});
Expand Down Expand Up @@ -809,6 +839,21 @@ scalar Foo extends string;
});
});

it("keeps extends inline and breaks the template arguments when too long", async () => {
await assertFormat({
code: `
scalar Foo extends Base<FirstArgumentTypeName, SecondArgumentTypeName, ThirdArgumentTypeName>;
`,
expected: `
scalar Foo extends Base<
FirstArgumentTypeName,
SecondArgumentTypeName,
ThirdArgumentTypeName
>;
`,
});
});

it("format with template parameters", async () => {
await assertFormat({
code: `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ enum Versions {
v2023_12_01_preview: "2023-12-01-preview",
}

model Vault
is Azure.ResourceManager.Legacy.TrackedResourceWithOptionalLocation<VaultProperties, false> {
model Vault is Azure.ResourceManager.Legacy.TrackedResourceWithOptionalLocation<
VaultProperties,
false
> {
...ResourceNameParameter<
Resource = Vault,
KeyName = "vaultName",
Expand Down
11 changes: 5 additions & 6 deletions website/src/content/docs/release-notes/typespec-1-11-0.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@ model Example {
description: string;
}
model CreateAndReadExample
is FilterVisibility<
Example,
#{ all: #[Lifecycle.Create, Lifecycle.Read] },
"CreateAndRead{name}"
>;
model CreateAndReadExample is FilterVisibility<
Example,
#{ all: #[Lifecycle.Create, Lifecycle.Read] },
"CreateAndRead{name}"
>;
```

:::caution
Expand Down
Loading