Skip to content

Commit

Permalink
Backmerge/release/november 2024 2024 11 28 (#1927)
Browse files Browse the repository at this point in the history
Co-authored-by: iscai-msft <[email protected]>
  • Loading branch information
tadelesh and iscai-msft authored Nov 28, 2024
1 parent a24339d commit 3ae22de
Show file tree
Hide file tree
Showing 14 changed files with 326 additions and 36 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"fix-version-mismatch": "syncpack fix-mismatches",
"format": "prettier --write .",
"format:check": "prettier . --check",
"format:dir": "prettier --write",
"lint": "eslint . --max-warnings=0",
"lint:fix": "eslint . --fix",
"pack:all": "chronus pack --pack-destination ./temp/artifacts",
Expand Down
12 changes: 12 additions & 0 deletions packages/typespec-client-generator-core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Change Log - @azure-tools/typespec-client-generator-core

## 0.48.3

### Bug Fixes

- [#1907](https://github.com/Azure/typespec-azure/pull/1907) use the right path parameter name when filtering method parameter

### Features

- [#1919](https://github.com/Azure/typespec-azure/pull/1919) support typespec common paging
- [#1918](https://github.com/Azure/typespec-azure/pull/1918) remove none visibility property for model


## 0.48.2

### Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion packages/typespec-client-generator-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@azure-tools/typespec-client-generator-core",
"version": "0.48.2",
"version": "0.48.3",
"author": "Microsoft Corporation",
"description": "TypeSpec Data Plane Generation library",
"homepage": "https://azure.github.io/typespec-azure",
Expand Down
1 change: 1 addition & 0 deletions packages/typespec-client-generator-core/src/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,7 @@ export function createTCGCContext(program: Program, emitterName: string): TCGCCo
__clientToApiVersionClientDefaultValue: new Map(),
previewStringRegex: /-preview$/,
disableUsageAccessPropagationToBase: false,
__pagedResultSet: new Set(),
};
}

Expand Down
4 changes: 3 additions & 1 deletion packages/typespec-client-generator-core/src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,9 @@ function filterOutUselessPathParameters(
param.__raw &&
isPathParam(context.program, param.__raw) &&
httpOperation.parameters.parameters.filter(
(p) => p.type === "path" && p.name === getWireName(context, param.__raw!),
(p) =>
p.type === "path" &&
p.name === (getPathParamName(context.program, param.__raw!) ?? param.name),
).length === 0
) {
methodParameters.splice(i, 1);
Expand Down
3 changes: 2 additions & 1 deletion packages/typespec-client-generator-core/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export interface TCGCContext {
decoratorsAllowList?: string[];
previewStringRegex: RegExp;
disableUsageAccessPropagationToBase: boolean;
__pagedResultSet: Set<SdkType>;
}

export interface SdkContext<
Expand Down Expand Up @@ -595,7 +596,7 @@ export interface SdkBasicServiceMethod<TServiceOperation extends SdkServiceOpera
}

interface SdkPagingServiceMethodOptions {
__raw_paged_metadata: PagedResultMetadata;
__raw_paged_metadata?: PagedResultMetadata;
nextLinkPath?: string; // off means fake paging
nextLinkOperation?: SdkServiceOperation;
}
Expand Down
6 changes: 6 additions & 0 deletions packages/typespec-client-generator-core/src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ export const $lib = createTypeSpecLibrary({
default: `Cannot pass an empty value to the @clientNamespace decorator`,
},
},
"unexpected-pageable-operation-return-type": {
severity: "error",
messages: {
default: `Operation is pageable but does not return a correct type.`,
},
},
},
});

Expand Down
126 changes: 119 additions & 7 deletions packages/typespec-client-generator-core/src/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ import {
Diagnostic,
getDoc,
getNamespaceFullName,
getPagingOperation,
getService,
getSummary,
ignoreDiagnostics,
isList,
Model,
ModelProperty,
Operation,
Type,
} from "@typespec/compiler";
Expand Down Expand Up @@ -132,25 +135,96 @@ function getSdkPagingServiceMethod<TServiceOperation extends SdkServiceOperation
client: SdkClientType<TServiceOperation>,
): [SdkPagingServiceMethod<TServiceOperation>, readonly Diagnostic[]] {
const diagnostics = createDiagnosticCollector();
const pagedMetadata = getPagedResult(context.program, operation)!;

const basic = diagnostics.pipe(
getSdkBasicServiceMethod<TServiceOperation>(context, operation, client),
);
if (pagedMetadata.itemsProperty) {

// normal paging
if (isList(context.program, operation)) {
const pagingOperation = diagnostics.pipe(getPagingOperation(context.program, operation));

if (basic.response.type?.__raw?.kind !== "Model" || !pagingOperation) {
diagnostics.add(
createDiagnostic({
code: "unexpected-pageable-operation-return-type",
target: operation,
format: {
operationName: operation.name,
},
}),
);
// return as page method with no paging info
return diagnostics.wrap({
...basic,
kind: "paging",
});
}

basic.response.resultPath = getPropertyPathFromModel(
context,
basic.response.type?.__raw,
(p) => p === pagingOperation.output.pageItems.property,
);
const nextLinkPath = pagingOperation.output.nextLink
? getPropertyPathFromModel(
context,
basic.response.type?.__raw,
(p) => p === pagingOperation.output.nextLink!.property,
)
: undefined;

context.__pagedResultSet.add(basic.response.type);
// tcgc will let all paging method return a list of items
basic.response.type = diagnostics.pipe(
getClientTypeWithDiagnostics(context, pagedMetadata.itemsProperty.type),
getClientTypeWithDiagnostics(context, pagingOperation?.output.pageItems.property.type),
);

return diagnostics.wrap({
...basic,
kind: "paging",
nextLinkPath,
});
}

// azure core paging
const pagedMetadata = getPagedResult(context.program, operation)!;

if (basic.response.type?.__raw?.kind !== "Model" || !pagedMetadata.itemsProperty) {
diagnostics.add(
createDiagnostic({
code: "unexpected-pageable-operation-return-type",
target: operation,
format: {
operationName: operation.name,
},
}),
);
// return as page method with no paging info
return diagnostics.wrap({
...basic,
kind: "paging",
});
}
basic.response.resultPath = getPathFromSegment(

context.__pagedResultSet.add(basic.response.type);

// tcgc will let all paging method return a list of items
basic.response.type = diagnostics.pipe(
getClientTypeWithDiagnostics(context, pagedMetadata.itemsProperty.type),
);

basic.response.resultPath = getPropertyPathFromSegment(
context,
pagedMetadata.modelType,
pagedMetadata.itemsSegments,
);

return diagnostics.wrap({
...basic,
__raw_paged_metadata: pagedMetadata,
kind: "paging",
nextLinkPath: getPathFromSegment(
nextLinkPath: getPropertyPathFromSegment(
context,
pagedMetadata.modelType,
pagedMetadata?.nextLinkSegments,
Expand All @@ -167,7 +241,45 @@ function getSdkPagingServiceMethod<TServiceOperation extends SdkServiceOperation
});
}

function getPathFromSegment(context: TCGCContext, type: Model, segments?: string[]): string {
export function getPropertyPathFromModel(
context: TCGCContext,
model: Model,
predicate: (property: ModelProperty) => boolean,
): string | undefined {
const queue: { model: Model; path: ModelProperty[] }[] = [];

for (const prop of model.properties.values()) {
if (predicate(prop)) {
return getLibraryName(context, prop);
}
if (prop.type.kind === "Model") {
queue.push({ model: prop.type, path: [prop] });
}
}

while (queue.length > 0) {
const { model, path } = queue.shift()!;
for (const prop of model.properties.values()) {
if (predicate(prop)) {
return path
.concat(prop)
.map((s) => getLibraryName(context, s))
.join(".");
}
if (prop.type.kind === "Model") {
queue.push({ model: prop.type, path: path.concat(prop) });
}
}
}

return undefined;
}

function getPropertyPathFromSegment(
context: TCGCContext,
type: Model,
segments?: string[],
): string {
if (!segments || segments.length === 0) {
return "";
}
Expand Down Expand Up @@ -393,7 +505,7 @@ function getSdkServiceMethod<TServiceOperation extends SdkServiceOperation>(
client: SdkClientType<TServiceOperation>,
): [SdkServiceMethod<TServiceOperation>, readonly Diagnostic[]] {
const lro = getLroMetadata(context.program, operation);
const paging = getPagedResult(context.program, operation);
const paging = getPagedResult(context.program, operation) || isList(context.program, operation);
if (lro && paging) {
return getSdkLroPagingServiceMethod<TServiceOperation>(context, operation, client);
} else if (paging) {
Expand Down
14 changes: 7 additions & 7 deletions packages/typespec-client-generator-core/src/public-utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { getPagedResult } from "@azure-tools/typespec-azure-core";
import {
Diagnostic,
Enum,
Expand All @@ -15,6 +14,7 @@ import {
getFriendlyName,
getNamespaceFullName,
getProjectedName,
getVisibility,
ignoreDiagnostics,
listServices,
resolveEncodedName,
Expand Down Expand Up @@ -113,7 +113,11 @@ export function getEffectivePayloadType(context: TCGCContext, type: Model): Mode
return type;
}

const effective = getEffectiveModelType(program, type, (t) => !isMetadata(context.program, t));
const effective = getEffectiveModelType(
program,
type,
(t) => !isMetadata(context.program, t) && !getVisibility(context.program, t)?.includes("none"), // eslint-disable-line @typescript-eslint/no-deprecated
);
if (effective.name) {
return effective;
}
Expand Down Expand Up @@ -691,9 +695,5 @@ export function isAzureCoreModel(t: SdkType): boolean {
* @returns
*/
export function isPagedResultModel(context: TCGCContext, t: SdkType): boolean {
return (
t.__raw !== undefined &&
t.__raw.kind === "Model" &&
getPagedResult(context.program, t.__raw) !== undefined
);
return context.__pagedResultSet.has(t);
}
1 change: 1 addition & 0 deletions packages/typespec-client-generator-core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1332,6 +1332,7 @@ function addPropertiesToModelType(
if (
isStatusCode(context.program, property) ||
isNeverOrVoidType(property.type) ||
getVisibility(context.program, property)?.includes("none") || // eslint-disable-line @typescript-eslint/no-deprecated
sdkType.kind !== "model"
) {
continue;
Expand Down
Loading

0 comments on commit 3ae22de

Please sign in to comment.