Skip to content

Commit 5fe6a87

Browse files
committed
Added interface changes for multiple file support
1 parent 0ac772a commit 5fe6a87

File tree

2 files changed

+187
-58
lines changed

2 files changed

+187
-58
lines changed

packages/typespec-autorest/src/openapi.ts

Lines changed: 14 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,13 @@ import {
174174
XmlObject,
175175
XmsPageable,
176176
} from "./openapi2-document.js";
177-
import type { AutorestEmitterResult, LoadedExample } from "./types.js";
177+
import {
178+
LateBoundReference,
179+
PendingSchema,
180+
ProcessedSchema,
181+
type AutorestEmitterResult,
182+
type LoadedExample,
183+
} from "./types.js";
178184
import { AutorestEmitterContext, getClientName, resolveOperationId } from "./utils.js";
179185
import { resolveXmlModule } from "./xml.js";
180186

@@ -232,56 +238,6 @@ export interface AutorestDocumentEmitterOptions {
232238
readonly xmlStrategy: "xml-service" | "none";
233239
}
234240

235-
/**
236-
* Represents a node that will hold a JSON reference. The value is computed
237-
* at the end so that we can defer decisions about the name that is
238-
* referenced.
239-
*/
240-
class Ref {
241-
value?: string;
242-
toJSON() {
243-
compilerAssert(this.value, "Reference value never set.");
244-
return this.value;
245-
}
246-
}
247-
248-
/**
249-
* Represents a non-inlined schema that will be emitted as a definition.
250-
* Computation of the OpenAPI schema object is deferred.
251-
*/
252-
interface PendingSchema {
253-
/** The TYPESPEC type for the schema */
254-
type: Type;
255-
256-
/** The visibility to apply when computing the schema */
257-
visibility: Visibility;
258-
259-
/**
260-
* The JSON reference to use to point to this schema.
261-
*
262-
* Note that its value will not be computed until all schemas have been
263-
* computed as we will add a suffix to the name if more than one schema
264-
* must be emitted for the type for different visibilities.
265-
*/
266-
ref: Ref;
267-
268-
/**
269-
* Determines the schema name if an override has been set
270-
* @param name The default name of the schema
271-
* @param visibility The visibility in which the schema is used
272-
* @returns The name of the given schema in the given visibility context
273-
*/
274-
getSchemaNameOverride?: (name: string, visibility: Visibility) => string;
275-
}
276-
277-
/**
278-
* Represents a schema that is ready to emit as its OpenAPI representation
279-
* has been produced.
280-
*/
281-
interface ProcessedSchema extends PendingSchema {
282-
schema: OpenAPI2Schema | undefined;
283-
}
284-
285241
type HttpParameterProperties = Extract<
286242
HttpProperty,
287243
{ kind: "header" | "query" | "path" | "cookie" }
@@ -340,7 +296,7 @@ export async function getOpenAPIForService(
340296
const pendingSchemas = new TwoLevelMap<Type, Visibility, PendingSchema>();
341297

342298
// Reuse a single ref object per Type+Visibility combination.
343-
const refs = new TwoLevelMap<Type, Visibility, Ref>();
299+
const refs = new TwoLevelMap<Type, Visibility, LateBoundReference>();
344300

345301
// Keep track of inline types still in the process of having their schema computed
346302
// This is used to detect cycles in inline types, which is an
@@ -561,7 +517,9 @@ export async function getOpenAPIForService(
561517
}
562518
}
563519

564-
function getFinalStateSchema(metadata: LroMetadata): { "final-state-schema": Ref } | undefined {
520+
function getFinalStateSchema(
521+
metadata: LroMetadata,
522+
): { "final-state-schema": LateBoundReference } | undefined {
565523
if (
566524
metadata.finalResult !== undefined &&
567525
metadata.finalResult !== "void" &&
@@ -571,14 +529,14 @@ export async function getOpenAPIForService(
571529
const schemaOrRef = resolveExternalRef(metadata.finalResult);
572530

573531
if (schemaOrRef !== undefined) {
574-
const ref = new Ref();
532+
const ref = new LateBoundReference();
575533
ref.value = schemaOrRef.$ref;
576534
return { "final-state-schema": ref };
577535
}
578536
const pending = pendingSchemas.getOrAdd(metadata.finalResult, Visibility.Read, () => ({
579537
type: model,
580538
visibility: Visibility.Read,
581-
ref: refs.getOrAdd(model, Visibility.Read, () => new Ref()),
539+
ref: refs.getOrAdd(model, Visibility.Read, () => new LateBoundReference()),
582540
}));
583541
return { "final-state-schema": pending.ref };
584542
}
@@ -1016,7 +974,7 @@ export async function getOpenAPIForService(
1016974
const pending = pendingSchemas.getOrAdd(type, schemaContext.visibility, () => ({
1017975
type,
1018976
visibility: schemaContext.visibility,
1019-
ref: refs.getOrAdd(type, schemaContext.visibility, () => new Ref()),
977+
ref: refs.getOrAdd(type, schemaContext.visibility, () => new LateBoundReference()),
1020978
getSchemaNameOverride: schemaNameOverride,
1021979
}));
1022980
return { $ref: pending.ref };

packages/typespec-autorest/src/types.ts

Lines changed: 173 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
1-
import type { Service, SourceFile } from "@typespec/compiler";
2-
import type { OpenAPI2Document } from "./openapi2-document.js";
1+
import { getResourceFeature } from "@azure-tools/typespec-azure-resource-manager";
2+
import {
3+
compilerAssert,
4+
Program,
5+
type ModelProperty,
6+
type Operation,
7+
type Service,
8+
type SourceFile,
9+
type Type,
10+
} from "@typespec/compiler";
11+
import { TwoLevelMap } from "@typespec/compiler/utils";
12+
import { Visibility } from "@typespec/http";
13+
import type {
14+
OpenAPI2Document,
15+
OpenAPI2Parameter,
16+
OpenAPI2PathItem,
17+
OpenAPI2Schema,
18+
Refable,
19+
} from "./openapi2-document.js";
320

421
/**
522
* A record containing the the OpenAPI 3 documents corresponding to
@@ -53,10 +70,164 @@ export interface AutorestEmitterResult {
5370

5471
/** Output file used */
5572
readonly outputFile: string;
73+
74+
/** The feature associated with this file, if any */
75+
readonly feature?: string;
5676
}
5777

5878
export interface LoadedExample {
5979
readonly relativePath: string;
6080
readonly file: SourceFile;
6181
readonly data: any;
6282
}
83+
84+
/**
85+
* Represents a node that will hold a JSON reference. The value is computed
86+
* at the end so that we can defer decisions about the name that is
87+
* referenced.
88+
*/
89+
export class LateBoundReference {
90+
isLocal?: boolean;
91+
file?: string;
92+
value?: string;
93+
setLocalValue(program: Program, inValue: string, type?: Type): void {
94+
if (type) {
95+
switch (type.kind) {
96+
case "Model":
97+
this.file = getResourceFeature(program, type);
98+
break;
99+
default:
100+
this.file = "common";
101+
}
102+
}
103+
this.isLocal = true;
104+
this.value = inValue;
105+
}
106+
setRemoteValue(inValue: string): void {
107+
this.isLocal = false;
108+
this.value = inValue;
109+
}
110+
toJSON() {
111+
compilerAssert(this.value, "Reference value never set.");
112+
if (!this.isLocal) return this.value;
113+
if (this.file === undefined) return `#/definitions/${this.value}`;
114+
return `${this.file}/definitions/${this.value}`;
115+
}
116+
}
117+
118+
/**
119+
* Represents a non-inlined schema that will be emitted as a definition.
120+
* Computation of the OpenAPI schema object is deferred.
121+
*/
122+
export interface PendingSchema {
123+
/** The TYPESPEC type for the schema */
124+
type: Type;
125+
126+
/** The visibility to apply when computing the schema */
127+
visibility: Visibility;
128+
129+
/**
130+
* The JSON reference to use to point to this schema.
131+
*
132+
* Note that its value will not be computed until all schemas have been
133+
* computed as we will add a suffix to the name if more than one schema
134+
* must be emitted for the type for different visibilities.
135+
*/
136+
ref: LateBoundReference;
137+
138+
/**
139+
* Determines the schema name if an override has been set
140+
* @param name The default name of the schema
141+
* @param visibility The visibility in which the schema is used
142+
* @returns The name of the given schema in the given visibility context
143+
*/
144+
getSchemaNameOverride?: (name: string, visibility: Visibility) => string;
145+
}
146+
147+
/**
148+
* Represents a schema that is ready to emit as its OpenAPI representation
149+
* has been produced.
150+
*/
151+
export interface ProcessedSchema extends PendingSchema {
152+
schema: OpenAPI2Schema | undefined;
153+
}
154+
155+
/** Abstracts away methods to create a OpenAPI 2.0 document ragardless of layout. */
156+
export interface OpenApi2DocumentProxy {
157+
/**
158+
* Resolve the logical OpenAPI document into a set of emitter results
159+
*/
160+
resolveDocuments(): Promise<AutorestEmitterResult[]>;
161+
/**
162+
* Get the parameters for an operation
163+
* @param op The operation to get parameters for
164+
*/
165+
getParameters(op: Operation): Map<ModelProperty, OpenAPI2Parameter>;
166+
/** Add a tag to an operation
167+
* @param op The operation to add a tag to
168+
* @param tag The tag to add
169+
*/
170+
addTag(op: Operation, tag: string): void;
171+
/**
172+
* Add a produces MIME type to an operation
173+
* @param op The operation to add the produces MIME type to
174+
* @param produces The MIME type to add
175+
*/
176+
addProduces(op: Operation, produces: string): void;
177+
178+
/**
179+
* Add a consumes MIME type to an operation
180+
* @param op The operation to add the consumes MIME type to
181+
* @param consumes The MIME type to add
182+
*/
183+
addConsumes(op: Operation, consumes: string): void;
184+
185+
/**
186+
* Add examples to an operation
187+
* @param op The operation to add examples to
188+
* @param examples The examples to add
189+
*/
190+
addExamples(op: Operation, examples: LoadedExample[]): void;
191+
192+
/**
193+
* get the tags for an operation
194+
* @param op The operation to get tags for
195+
*/
196+
getTags(op: Operation): Set<string>;
197+
198+
/**
199+
* Get the consumes MIME types for an operation
200+
* @param op The operation to get consumes MIME types for
201+
*/
202+
getConsumes(op: Operation): Set<string>;
203+
204+
/**
205+
* Get the produces MIME types for an operation
206+
* @param op The operation to get produces MIME types for
207+
*/
208+
getProduces(op: Operation): Set<string>;
209+
210+
/**
211+
* Get or add the path associated with the given operation
212+
* @param op The operation to get or add the path for
213+
*/
214+
createOrAddPathItem(op: Operation): OpenAPI2PathItem;
215+
216+
/**
217+
* Get the file name for a given type
218+
* @param type The type to get the file name for
219+
*/
220+
getFile(type: Type): string | undefined;
221+
222+
/**
223+
* Get or add a parameter placeholder for a given property
224+
* @param property The property to get or add the parameter placeholder for
225+
*/
226+
getOrAddParamPlaceholder(property: ModelProperty): Refable<OpenAPI2Parameter>;
227+
228+
/** The schemas that are not yet resolved */
229+
pendingSchemas: TwoLevelMap<Type, Visibility, PendingSchema>;
230+
231+
/** references included in schemas */
232+
refs: TwoLevelMap<Type, Visibility, LateBoundReference>;
233+
}

0 commit comments

Comments
 (0)