Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propogate api version #805

Merged
merged 9 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from 7 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
Expand Up @@ -605,7 +605,7 @@ export function createSdkContext<
apiVersion: options?.versionStrategy === "ignore" ? "all" : context.options["api-version"],
originalProgram: context.program,
__namespaceToApiVersionParameter: new Map(),
__namespaceToApiVersions: new Map(),
__tspTypeToApiVersions: new Map(),
__namespaceToApiVersionClientDefaultValue: new Map(),
};
sdkContext.experimental_sdkPackage = getSdkPackage(sdkContext);
Expand Down
31 changes: 22 additions & 9 deletions packages/typespec-client-generator-core/src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ import {
export function getSdkHttpOperation(
context: TCGCContext,
httpOperation: HttpOperation,
methodParameters: SdkMethodParameter[]
methodParameters: SdkMethodParameter[],
): [SdkHttpOperation, readonly Diagnostic[]] {
const diagnostics = createDiagnosticCollector();
const { responses, exceptions } = diagnostics.pipe(
Expand All @@ -70,7 +70,12 @@ export function getSdkHttpOperation(
.concat([...exceptions.values()])
.filter((r) => r.type);
const parameters = diagnostics.pipe(
getSdkHttpParameters(context, httpOperation, methodParameters, responsesWithBodies[0])
getSdkHttpParameters(
context,
httpOperation,
methodParameters,
responsesWithBodies[0]
)
);
return diagnostics.wrap({
__raw: httpOperation,
Expand Down Expand Up @@ -112,7 +117,9 @@ function getSdkHttpParameters(
retval.parameters = httpOperation.parameters.parameters
.filter((x) => !isNeverOrVoidType(x.param.type))
.map((x) =>
diagnostics.pipe(getSdkHttpParameter(context, x.param, httpOperation.operation, x.type))
diagnostics.pipe(
getSdkHttpParameter(context, x.param, httpOperation.operation, x.type)
)
)
.filter(
(x): x is SdkHeaderParameter | SdkQueryParameter | SdkPathParameter =>
Expand All @@ -129,7 +136,12 @@ function getSdkHttpParameters(
// if there's a param on the body, we can just rely on getSdkHttpParameter
if (tspBody.parameter && !isNeverOrVoidType(tspBody.parameter.type)) {
const getParamResponse = diagnostics.pipe(
getSdkHttpParameter(context, tspBody.parameter, httpOperation.operation, "body")
getSdkHttpParameter(
context,
tspBody.parameter,
httpOperation.operation,
"body"
)
);
if (getParamResponse.kind !== "body") {
diagnostics.add(
Expand Down Expand Up @@ -165,7 +177,7 @@ function getSdkHttpParameters(
apiVersions: getAvailableApiVersions(
context,
tspBody.type,
httpOperation.operation.namespace
httpOperation.operation,
),
type,
optional: false,
Expand Down Expand Up @@ -304,7 +316,9 @@ export function getSdkHttpParameter(
location?: "path" | "query" | "header" | "body"
): [SdkHttpParameter, readonly Diagnostic[]] {
const diagnostics = createDiagnosticCollector();
const base = diagnostics.pipe(getSdkModelPropertyTypeBase(context, type, operation));
const base = diagnostics.pipe(
getSdkModelPropertyTypeBase(context, type, operation)
);
const program = context.program;
const correspondingMethodParams: SdkParameter[] = []; // we set it later in the operation
if (isPathParam(context.program, type) || location === "path") {
Expand Down Expand Up @@ -370,7 +384,7 @@ export function getSdkHttpParameter(

function getSdkHttpResponseAndExceptions(
context: TCGCContext,
httpOperation: HttpOperation
httpOperation: HttpOperation,
): [
{
responses: Map<HttpStatusCodeRange | number, SdkHttpResponse>;
Expand Down Expand Up @@ -427,7 +441,6 @@ function getSdkHttpResponseAndExceptions(
: innerResponse.body.type;
}
}

const sdkResponse: SdkHttpResponse = {
__raw: response,
kind: "http",
Expand All @@ -440,7 +453,7 @@ function getSdkHttpResponseAndExceptions(
apiVersions: getAvailableApiVersions(
context,
httpOperation.operation,
httpOperation.operation.namespace
httpOperation.operation,
),
nullable: body ? isNullable(body) : true,
};
Expand Down
40 changes: 28 additions & 12 deletions packages/typespec-client-generator-core/src/internal-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,11 @@ export function filterApiVersionsWithDecorators(
return retval;
}

function sortAndRemoveDuplicates(a: string[], b: string[], apiVersions: string[]): string[] {
const union = Array.from(new Set([...a, ...b]));
return apiVersions.filter(item => union.includes(item));
}

/**
*
* @param context
Expand All @@ -167,20 +172,31 @@ export function filterApiVersionsWithDecorators(
export function getAvailableApiVersions(
context: TCGCContext,
type: Type,
namespace?: Namespace | Interface
wrapper?: Type,
): string[] {
let cachedApiVersions: string[] = [];
if (namespace) {
cachedApiVersions = context.__namespaceToApiVersions.get(namespace) || [];
let wrapperApiVersions: string[] = [];
if (wrapper) {
wrapperApiVersions = context.__tspTypeToApiVersions.get(wrapper) || [];
}

const apiVersions =
cachedApiVersions ||
getVersions(context.program, type)[1]
?.getVersions()
.map((x) => x.value);
const allApiVersions = getVersions(context.program, type)[1]
?.getVersions()
.map((x) => x.value) || [];

const apiVersions = wrapperApiVersions.length ? wrapperApiVersions : allApiVersions;
if (!apiVersions) return [];
return filterApiVersionsWithDecorators(context, type, apiVersions);
const explicitlyDecorated = filterApiVersionsWithDecorators(context, type, apiVersions);
if (explicitlyDecorated.length) {
context.__tspTypeToApiVersions.set(type, explicitlyDecorated);
return explicitlyDecorated
}
// we take the union of all of the api versions that the type is available on
// if it's called multiple times with diff wrappers, we want to make sure we have
// all of the possible api versions listed
const existing = context.__tspTypeToApiVersions.get(type) || [];
const retval = sortAndRemoveDuplicates(wrapperApiVersions, existing, allApiVersions)
context.__tspTypeToApiVersions.set(type, retval);
return retval;
}

interface DocWrapper {
Expand Down Expand Up @@ -303,7 +319,7 @@ export interface TCGCContext {
httpOperationCache?: Map<Operation, HttpOperation>;
unionsMap?: Map<Union, SdkUnionType>;
__namespaceToApiVersionParameter: Map<Interface | Namespace, SdkParameter>;
__namespaceToApiVersions: Map<Interface | Namespace, string[]>;
__tspTypeToApiVersions: Map<Type, string[]>;
__namespaceToApiVersionClientDefaultValue: Map<Interface | Namespace, string | undefined>;
knownScalars?: Record<string, SdkBuiltInKinds>;
diagnostics: readonly Diagnostic[];
Expand All @@ -321,7 +337,7 @@ export function createTCGCContext(program: Program): TCGCContext {
diagnostics: [],
originalProgram: program,
__namespaceToApiVersionParameter: new Map(),
__namespaceToApiVersions: new Map(),
__tspTypeToApiVersions: new Map(),
__namespaceToApiVersionClientDefaultValue: new Map(),
};
}
Expand Down
Loading
Loading