Skip to content

Commit

Permalink
Autorest generated dec sig (#1199)
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheeguerin authored Jul 18, 2024
1 parent a2c7560 commit 5a4f789
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 21 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
changeKind: internal
packages:
- "@azure-tools/typespec-autorest"
---

29 changes: 29 additions & 0 deletions packages/typespec-autorest/generated-defs/Autorest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { DecoratorContext, Model, ModelProperty, Operation } from "@typespec/compiler";

/**
* `@example` - attaches example files to an operation. Multiple examples can be specified.
*
* `@example` can be specified on Operations.
*
* @param pathOrUri path or Uri to the example file.
* @param title name or description of the example file.
*/
export type ExampleDecorator = (
context: DecoratorContext,
target: Operation,
pathOrUri: string,
title: string
) => void;

/**
* `@useRef` - is used to replace the TypeSpec model type in emitter output with a pre-existing named OpenAPI schema such as Azure Resource Manager common types.
*
* `@useRef` can be specified on Models and ModelProperty.
*
* @param jsonRef path or Uri to an OpenAPI schema.
*/
export type UseRefDecorator = (
context: DecoratorContext,
entity: Model | ModelProperty,
jsonRef: string
) => void;
14 changes: 14 additions & 0 deletions packages/typespec-autorest/generated-defs/Autorest.ts-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/** An error here would mean that the decorator is not exported or doesn't have the right name. */
import { $example, $useRef } from "@azure-tools/typespec-autorest";
import type { ExampleDecorator, UseRefDecorator } from "./Autorest.js";

type Decorators = {
$example: ExampleDecorator;
$useRef: UseRefDecorator;
};

/** An error here would mean that the exported decorator is not using the same signature. Make sure to have export const $decName: DecNameDecorator = (...) => ... */
const _: Decorators = {
$example,
$useRef,
};
3 changes: 2 additions & 1 deletion packages/typespec-autorest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
},
"scripts": {
"clean": "rimraf ./dist ./temp",
"build": "npm run regen-autorest-openapi-schema && tsc -p . && npm run lint-typespec-library",
"build": "npm run gen-extern-signature && npm run regen-autorest-openapi-schema && tsc -p . && npm run lint-typespec-library",
"watch": "tsc -p . --watch",
"gen-extern-signature": "tspd --enable-experimental gen-extern-signature .",
"lint-typespec-library": "tsp compile . --warn-as-error --import @typespec/library-linter --no-emit",
"regen-autorest-openapi-schema": "tsp compile ./schema/autorest-openapi-schema.tsp --warn-as-error && node ./.scripts/schema-json-to-js.js",
"test": "vitest run",
Expand Down
33 changes: 18 additions & 15 deletions packages/typespec-autorest/src/decorators.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DecoratorContext, Model, ModelProperty, Program, Type } from "@typespec/compiler";
import { createStateSymbol, reportDiagnostic } from "./lib.js";
import { ExampleDecorator, UseRefDecorator } from "../generated-defs/Autorest.js";
import { AutorestStateKeys, reportDiagnostic } from "./lib.js";

export const namespace = "Autorest";

Expand All @@ -8,7 +9,6 @@ export interface Example {
title: string;
}

const exampleKey = createStateSymbol("example");
/**
* `@example` - attaches example files to an operation. Multiple examples can be specified.
*
Expand All @@ -17,18 +17,18 @@ const exampleKey = createStateSymbol("example");
*
* `@example` can be specified on Operations.
*/
export function $example(
export const $example: ExampleDecorator = (
context: DecoratorContext,
entity: Type,
pathOrUri: string,
title: string
) {
) => {
const { program } = context;
if (!program.stateMap(exampleKey).has(entity)) {
program.stateMap(exampleKey).set(entity, []);
if (!program.stateMap(AutorestStateKeys.example).has(entity)) {
program.stateMap(AutorestStateKeys.example).set(entity, []);
} else if (
program
.stateMap(exampleKey)
.stateMap(AutorestStateKeys.example)
.get(entity)
.find((e: Example) => e.title === title || e.pathOrUri === pathOrUri)
) {
Expand All @@ -37,29 +37,32 @@ export function $example(
target: entity,
});
}
program.stateMap(exampleKey).get(entity).push({
program.stateMap(AutorestStateKeys.example).get(entity).push({
pathOrUri,
title,
});
}
};

export function getExamples(program: Program, entity: Type): Example[] | undefined {
return program.stateMap(exampleKey).get(entity);
return program.stateMap(AutorestStateKeys.example).get(entity);
}

const refTargetsKey = createStateSymbol("autorest.ref");
/**
* `@useRef` - is used to replace the TypeSpec model type in emitter output with a pre-existing named OpenAPI schema such as ARM common types.
*
* @param {string} param jsonRef - path or Uri to an OpenAPI schema.
*
* `@useRef` can be specified on Models and ModelProperty.
*/
export function $useRef(context: DecoratorContext, entity: Model | ModelProperty, jsonRef: string) {
context.program.stateMap(refTargetsKey).set(entity, jsonRef);
}
export const $useRef: UseRefDecorator = (
context: DecoratorContext,
entity: Model | ModelProperty,
jsonRef: string
) => {
context.program.stateMap(AutorestStateKeys.useRef).set(entity, jsonRef);
};

export function getRef(program: Program, entity: Type): string | undefined {
const refOrProducer = program.stateMap(refTargetsKey).get(entity);
const refOrProducer = program.stateMap(AutorestStateKeys.useRef).get(entity);
return refOrProducer;
}
12 changes: 8 additions & 4 deletions packages/typespec-autorest/src/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ const EmitterOptionsSchema: JSONSchemaType<AutorestEmitterOptions> = {
required: [],
};

const libDef = {
export const $lib = createTypeSpecLibrary({
name: "@azure-tools/typespec-autorest",
diagnostics: {
"duplicate-body-types": {
Expand Down Expand Up @@ -343,7 +343,11 @@ const libDef = {
emitter: {
options: EmitterOptionsSchema as JSONSchemaType<AutorestEmitterOptions>,
},
} as const;

export const $lib = createTypeSpecLibrary(libDef);
export const { reportDiagnostic, createDiagnostic, createStateSymbol, getTracer } = $lib;
state: {
example: { description: "State for the @example decorator" },
useRef: { description: "State for the @useRef decorator" },
},
} as const);

export const { reportDiagnostic, createDiagnostic, stateKeys: AutorestStateKeys, getTracer } = $lib;
2 changes: 1 addition & 1 deletion packages/typespec-autorest/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@
"rootDir": ".",
"tsBuildInfoFile": "temp/tsconfig.tsbuildinfo"
},
"include": ["src/**/*.ts", "test/**/*.ts"]
"include": ["src/**/*.ts", "generated-defs/**/*.ts", "test/**/*.ts"]
}

0 comments on commit 5a4f789

Please sign in to comment.