зеркало из https://github.com/Azure/autorest.git
Родитель
5b4c129074
Коммит
46f67be213
|
@ -2,13 +2,37 @@
|
|||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"diagnosticLogging": true,
|
||||
"type": "node2",
|
||||
"type": "node",
|
||||
"protocol": "inspector",
|
||||
"request": "launch",
|
||||
"name": "run tests",
|
||||
"program": "${workspaceRoot}/src/autorest-core/node_modules/mocha/bin/_mocha",
|
||||
"args": [
|
||||
"test",
|
||||
"-g",
|
||||
"TestConfiguration"
|
||||
],
|
||||
"cwd": "${workspaceRoot}/src/autorest-core"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"protocol": "inspector",
|
||||
"request": "launch",
|
||||
"name": "run bootstrapper",
|
||||
"program": "${workspaceRoot}/src/autorest/app.js",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"preLaunchTask": "build/typescript"
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"protocol": "inspector",
|
||||
"request": "launch",
|
||||
"name": "run autorest",
|
||||
"program": "${workspaceRoot}/src/autorest-core/app.js",
|
||||
"args" : [
|
||||
"C:/work/github/azure-rest-api-specs/profile/all.md"
|
||||
],
|
||||
"cwd": "${workspaceRoot}"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,3 +1,2 @@
|
|||
ERROR: Syntax error: Invalid YAML object.
|
||||
- /Samples/test/error-behavior/config-bad-syntax/readme.md:6:0
|
||||
Error occurred. Exiting.
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
Error occurred. Exiting.
|
||||
{ Error: Error occurred. Exiting.
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
|
@ -7,4 +7,3 @@ ERROR: Syntax Error Encountered: Syntax error: bad indentation of a mapping entr
|
|||
ERROR: Syntax Error Encountered: Syntax error: bad indentation of a mapping entry
|
||||
- /Samples/test/error-behavior/openapi-md-bad-syntax/tiny.md:65:18
|
||||
FATAL: loader - FAILED
|
||||
Error occurred. Exiting.
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
Process() Cancelled due to exception : Error occurred. Exiting.
|
||||
Error occurred. Exiting.
|
||||
{ Error: Error occurred. Exiting.
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
|
@ -1,4 +1,3 @@
|
|||
ERROR: Referenced file '/Samples/test/error-behavior/openapi-yaml-bad-file-reference/i-do-not-exist.json' not found
|
||||
- /Samples/test/error-behavior/openapi-yaml-bad-file-reference/tiny.yaml:23:10
|
||||
FATAL: loader - FAILED
|
||||
Error occurred. Exiting.
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
Process() Cancelled due to exception : Error occurred. Exiting.
|
||||
Error occurred. Exiting.
|
||||
{ Error: Error occurred. Exiting.
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
|
@ -0,0 +1 @@
|
|||
Process() Cancelled due to exception : Plugin modeler reported failure.
|
|
@ -14,6 +14,7 @@ import { Parse, Stringify } from './lib/ref/yaml';
|
|||
import { CreateObject, nodes } from './lib/ref/jsonpath';
|
||||
import { OutstandingTaskAwaiter } from "./lib/outstanding-task-awaiter";
|
||||
import { AutoRest } from "./lib/autorest-core";
|
||||
import { ShallowCopy } from "./lib/source-map/merging"
|
||||
import { Message, Channel } from "./lib/message";
|
||||
import { resolve as currentDirectory } from "path";
|
||||
import { ChildProcess } from "child_process";
|
||||
|
@ -23,19 +24,21 @@ import { isLegacy, CreateConfiguration } from "./legacyCli";
|
|||
import { DataStore } from "./lib/data-store/data-store";
|
||||
import { RealFileSystem } from "./lib/file-system";
|
||||
import { Exception, OperationCanceledException } from './lib/exception';
|
||||
import { Console } from "./lib/console"
|
||||
import { exists } from "./lib/ref/async"
|
||||
|
||||
/**
|
||||
* Legacy AutoRest
|
||||
*/
|
||||
|
||||
function awaitable(child: ChildProcess): Promise<number> {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise<number>((resolve, reject) => {
|
||||
child.addListener("error", reject);
|
||||
child.addListener("exit", resolve);
|
||||
});
|
||||
}
|
||||
|
||||
async function legacyMain(autorestArgs: string[]): Promise<void> {
|
||||
async function legacyMain(autorestArgs: string[]): Promise<number> {
|
||||
if (autorestArgs.indexOf("-FANCY") !== -1) {
|
||||
// generate virtual config file
|
||||
const currentDirUri = CreateFolderUri(currentDirectory());
|
||||
|
@ -46,7 +49,7 @@ async function legacyMain(autorestArgs: string[]): Promise<void> {
|
|||
if (autorestArgs[0] === "init") {
|
||||
const clientNameGuess = (config["override-info"] || {}).title || Parse<any>(await ReadUri(config["input-file"][0])).info.title;
|
||||
await autorestInit(clientNameGuess, Array.isArray(config["input-file"]) ? config["input-file"] as any : []);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
// autorest init-min
|
||||
if (autorestArgs[0] === "init-min") {
|
||||
|
@ -61,7 +64,7 @@ ${Stringify(config).replace(/^---\n/, "")}
|
|||
~~~
|
||||
|
||||
`.replace(/~/g, "`"));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
// autorest init-cli
|
||||
if (autorestArgs[0] === "init-cli") {
|
||||
|
@ -74,7 +77,7 @@ ${Stringify(config).replace(/^---\n/, "")}
|
|||
}
|
||||
}
|
||||
console.log(args.join(" "));
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
config["base-folder"] = currentDirUri;
|
||||
|
@ -82,24 +85,7 @@ ${Stringify(config).replace(/^---\n/, "")}
|
|||
await api.AddConfiguration(config);
|
||||
const outstanding = new OutstandingTaskAwaiter();
|
||||
api.GeneratedFile.Subscribe((_, file) => outstanding.Await(WriteString(file.uri, file.content)));
|
||||
//api.Debug.Subscribe((_, m) => console.log(m.Text));
|
||||
//api.Verbose.Subscribe((_, m) => console.log(m.Text));
|
||||
api.Message.Subscribe((_, m) => {
|
||||
switch (m.Channel) {
|
||||
case Channel.Information:
|
||||
console.log(m.Text);
|
||||
break;
|
||||
case Channel.Warning:
|
||||
console.warn(m.Text);
|
||||
break;
|
||||
case Channel.Error:
|
||||
console.error(m.Text);
|
||||
break;
|
||||
case Channel.Fatal:
|
||||
console.error(m.Text);
|
||||
break;
|
||||
}
|
||||
});
|
||||
subscribeMessages(api, () => { });
|
||||
|
||||
const result = await api.Process().finish;
|
||||
if (result != true) {
|
||||
|
@ -115,6 +101,8 @@ ${Stringify(config).replace(/^---\n/, "")}
|
|||
const exitCode = await awaitable(autorestExe);
|
||||
process.exit(exitCode);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -150,6 +138,33 @@ function parseArgs(autorestArgs: string[]): CommandLineArgs {
|
|||
return result;
|
||||
}
|
||||
|
||||
function subscribeMessages(api: AutoRest, errorCounter: () => void) {
|
||||
api.Message.Subscribe((_, m) => {
|
||||
switch (m.Channel) {
|
||||
case Channel.Information:
|
||||
console.log(m.Text);
|
||||
break;
|
||||
case Channel.Warning:
|
||||
console.warn(m.Text);
|
||||
break;
|
||||
case Channel.Error:
|
||||
errorCounter();
|
||||
console.error(m.Text);
|
||||
break;
|
||||
case Channel.Debug:
|
||||
console.log(m.Text);
|
||||
break;
|
||||
case Channel.Verbose:
|
||||
console.log(m.Text);
|
||||
break;
|
||||
case Channel.Fatal:
|
||||
errorCounter();
|
||||
console.error(m.Text);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function autorestInit(title: string = "API-NAME", inputs: string[] = ["LIST INPUT FILES HERE"]) {
|
||||
const cwdUri = CreateFolderUri(currentDirectory());
|
||||
for (let i = 0; i < inputs.length; ++i) {
|
||||
|
@ -200,43 +215,219 @@ csharp:
|
|||
`.replace(/~/g, "`"));
|
||||
}
|
||||
|
||||
async function currentMain(autorestArgs: string[]): Promise<void> {
|
||||
let exitcode = 0;
|
||||
const outstanding = new OutstandingTaskAwaiter();
|
||||
let args: CommandLineArgs;
|
||||
|
||||
async function currentMain(autorestArgs: string[]): Promise<number> {
|
||||
if (autorestArgs[0] === "init") {
|
||||
await autorestInit();
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const args = parseArgs(autorestArgs);
|
||||
// parse the args from the command line
|
||||
args = parseArgs(autorestArgs);
|
||||
|
||||
// identify where we are starting from.
|
||||
const currentDirUri = CreateFolderUri(currentDirectory());
|
||||
|
||||
// get an instance of AutoRest and add the command line switches to the configuration.
|
||||
const api = new AutoRest(new RealFileSystem(), ResolveUri(currentDirUri, args.configFileOrFolder || "."));
|
||||
for (const s of args.switches) {
|
||||
await api.AddConfiguration(s);
|
||||
}
|
||||
const outstanding = new OutstandingTaskAwaiter();
|
||||
api.AddConfiguration(args.switches);
|
||||
|
||||
// listen for output messages and file writes
|
||||
subscribeMessages(api, () => exitcode++);
|
||||
api.GeneratedFile.Subscribe((_, file) => outstanding.Await(WriteString(file.uri, file.content)));
|
||||
//api.Debug.Subscribe((_, m) => console.log(m.Text));
|
||||
//api.Verbose.Subscribe((_, m) => console.log(m.Text));
|
||||
api.Message.Subscribe((_, m) => {
|
||||
switch (m.Channel) {
|
||||
case Channel.Information:
|
||||
console.log(m.Text);
|
||||
break;
|
||||
case Channel.Warning:
|
||||
console.warn(m.Text);
|
||||
break;
|
||||
case Channel.Error:
|
||||
console.error(m.Text);
|
||||
break;
|
||||
case Channel.Fatal:
|
||||
console.error(m.Text);
|
||||
break;
|
||||
const config = (await api.view);
|
||||
|
||||
try {
|
||||
// is this a batch process?
|
||||
if (config["batch"]) {
|
||||
return await batch(api);
|
||||
}
|
||||
|
||||
// maybe a merge process
|
||||
if (config["merge"]) {
|
||||
return await merge(api);
|
||||
}
|
||||
|
||||
// Just regular ol' AutoRest!
|
||||
const result = await api.Process().finish;
|
||||
if (result != true) {
|
||||
throw result;
|
||||
}
|
||||
});
|
||||
const result = await api.Process().finish;
|
||||
if (result != true) {
|
||||
throw result;
|
||||
}
|
||||
await outstanding.Wait();
|
||||
finally {
|
||||
// wait for any outstanding file writes to complete before we bail.
|
||||
await outstanding.Wait();
|
||||
}
|
||||
|
||||
// return the exit code to the caller.
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
async function merge(api: AutoRest): Promise<number> {
|
||||
// get the configuration
|
||||
const config = await api.view;
|
||||
|
||||
for (const configFile of config.InputFileUris) {
|
||||
// let's get out of here if things are not going well.
|
||||
if (exitcode > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function shallowMerge(existing: any, more: any) {
|
||||
if (existing && more) {
|
||||
for (const key of Object.getOwnPropertyNames(more)) {
|
||||
const value = more[key];
|
||||
if (value !== undefined) {
|
||||
/* if (existing[key]) {
|
||||
Console.Log(`> Warning: ${key} is overwritten.`);
|
||||
} */
|
||||
existing[key] = value;
|
||||
}
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
||||
if (existing) {
|
||||
return existing;
|
||||
}
|
||||
return more;
|
||||
}
|
||||
|
||||
function getRds(schema: any, path: string): Array<string> {
|
||||
const rx = /.*\/(.*)\/(.*).json/;
|
||||
|
||||
const m = rx.exec(path) || [];
|
||||
const apiversion = m[1];
|
||||
const namespace = m[2];
|
||||
const result = [];
|
||||
if (schema.resourceDefinitions) {
|
||||
for (const name of Object.getOwnPropertyNames(schema.resourceDefinitions)) {
|
||||
result.push(`{ "$ref": "http://schema.management.azure.com/schemas/${apiversion}/${namespace}.json#/resourceDefinitions/${name}" }, `);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
async function batch(api: AutoRest): Promise<number> {
|
||||
// get the configuration
|
||||
const outputs = new Map<string, string>();
|
||||
const schemas = new Array<string>();
|
||||
|
||||
const config = await api.view;
|
||||
for (const batchConfig of config.GetNestedConfiguration("batch")) { // really, there should be only one
|
||||
for (const eachFile of batchConfig["input-file"]) {
|
||||
const path = ResolveUri(config.configFileFolderUri, eachFile);
|
||||
const content = await ReadUri(path);
|
||||
if (!AutoRest.IsSwaggerFile(content)) {
|
||||
exitcode++;
|
||||
Console.Error(`File ${path} is not a OpenAPI file.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create the autorest instance for that item
|
||||
const instance = new AutoRest(new RealFileSystem(), config.configFileFolderUri);
|
||||
instance.GeneratedFile.Subscribe((_, file) => {
|
||||
if (file.uri.endsWith(".json")) {
|
||||
const more = JSON.parse(file.content);
|
||||
if (!outputs.has(file.uri)) {
|
||||
// Console.Log(` Writing *${file.uri}*`);
|
||||
outputs.set(file.uri, file.content);
|
||||
outstanding.Await(WriteString(file.uri, file.content))
|
||||
schemas.push(...getRds(more, file.uri));
|
||||
return;
|
||||
} else {
|
||||
const existing = JSON.parse(<string>outputs.get(file.uri));
|
||||
// Console.Log(` Updating *${file.uri}*`);
|
||||
|
||||
schemas.push(...getRds(more, file.uri));
|
||||
existing.resourceDefinitions = shallowMerge(existing.resourceDefinitions, more.resourceDefinitions);
|
||||
existing.definitions = shallowMerge(existing.definitions, more.definitions);
|
||||
const content = JSON.stringify(existing, null, 2);
|
||||
outputs.set(file.uri, content);
|
||||
outstanding.Await(WriteString(file.uri, content));
|
||||
}
|
||||
}
|
||||
});
|
||||
subscribeMessages(instance, () => exitcode++);
|
||||
|
||||
// set configuration for that item
|
||||
instance.AddConfiguration(ShallowCopy(batchConfig, "input-file"));
|
||||
instance.AddConfiguration({ "input-file": eachFile });
|
||||
|
||||
const newView = await instance.view;
|
||||
// console.log(`Inputs: ${newView["input-file"]}`);
|
||||
|
||||
Console.Log(`Running autorest for *${path}* `);
|
||||
|
||||
// ok, kick off the process for that one.
|
||||
await instance.Process().finish.then((result) => {
|
||||
// console.log(`done: ${path}`);
|
||||
exitcode++;
|
||||
if (result != true) {
|
||||
throw result;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
await outstanding;
|
||||
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
|
||||
async function deprecatedBatch(api: AutoRest): Promise<number> {
|
||||
// get the configuration
|
||||
const config = await api.view;
|
||||
for (const batchConfig of config.GetNestedConfiguration("batch")) { // really, there should be only one
|
||||
for (const eachGeneration of batchConfig.GetNestedConfiguration("for-each")) {
|
||||
for (const configFile of eachGeneration["input-file"]) { // really, there should be only one here too.
|
||||
const path = ResolveUri(config.configFileFolderUri, configFile);
|
||||
const content = await ReadUri(path);
|
||||
if (!AutoRest.IsConfigurationFile(content)) {
|
||||
exitcode++;
|
||||
console.error(`File ${path} is not a AutoRest configuration file.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create the autorest instance for that item
|
||||
const instance = new AutoRest(new RealFileSystem(), path);
|
||||
instance.GeneratedFile.Subscribe((_, file) => {
|
||||
console.log(`writing ${file.uri}`);
|
||||
return outstanding.Await(WriteString(file.uri, file.content))
|
||||
});
|
||||
subscribeMessages(instance, () => exitcode++);
|
||||
|
||||
// set configuration for that item
|
||||
instance.AddConfiguration(ShallowCopy(eachGeneration, "input-file"));
|
||||
instance.AddConfiguration(ShallowCopy(batchConfig, "for-each"));
|
||||
|
||||
const newView = await instance.view;
|
||||
// console.log(`Inputs: ${newView["input-file"]}`);
|
||||
|
||||
console.log(`Running autorest for ${path} `);
|
||||
|
||||
// ok, kick off the process for that one.
|
||||
|
||||
await instance.Process().finish.then((result) => {
|
||||
console.log(`done: ${path}`);
|
||||
exitcode++;
|
||||
if (result != true) {
|
||||
throw result;
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,8 +435,12 @@ async function currentMain(autorestArgs: string[]): Promise<void> {
|
|||
*/
|
||||
|
||||
async function main() {
|
||||
let autorestArgs: Array<string> = [];
|
||||
|
||||
try {
|
||||
const autorestArgs = process.argv.slice(2);
|
||||
let exitcode: number = 0;
|
||||
|
||||
autorestArgs = process.argv.slice(2);
|
||||
|
||||
// temporary: --help displays legacy AutoRest's -Help message
|
||||
if (autorestArgs.indexOf("--help") !== -1) {
|
||||
|
@ -254,9 +449,9 @@ async function main() {
|
|||
}
|
||||
|
||||
if (isLegacy(autorestArgs)) {
|
||||
await legacyMain(autorestArgs);
|
||||
exitcode = await legacyMain(autorestArgs);
|
||||
} else {
|
||||
await currentMain(autorestArgs);
|
||||
exitcode = await currentMain(autorestArgs);
|
||||
}
|
||||
|
||||
// for relaxed profiling (assuming that no one calls `main` from electron... use AAAL!)
|
||||
|
@ -265,7 +460,11 @@ async function main() {
|
|||
process.exit(0);
|
||||
} catch (e) {
|
||||
if (e instanceof Exception) {
|
||||
console.error(e.message);
|
||||
console.log(e.message);
|
||||
|
||||
if (autorestArgs.indexOf("--debug")) {
|
||||
console.log(e);
|
||||
}
|
||||
process.exit(e.exitCode);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Stringify } from './ref/yaml';
|
|||
import { RunPipeline } from './pipeline/pipeline';
|
||||
import { SmartPosition, Position } from './ref/source-map';
|
||||
import { DataStore, Metadata } from './data-store/data-store';
|
||||
import { IEnumerable, From } from './ref/linq';
|
||||
import { IEnumerable, From, Push } from './ref/linq';
|
||||
import { IEvent, EventDispatcher, EventEmitter } from "./events";
|
||||
import { IFileSystem } from "./file-system";
|
||||
import { Configuration, ConfigurationView, MessageEmitter } from './configuration';
|
||||
|
@ -31,7 +31,7 @@ export class AutoRest extends EventEmitter {
|
|||
})();
|
||||
}
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param rootUri The rootUri of the workspace. Is null if no workspace is open.
|
||||
* @param fileSystem The implementation of the filesystem to load and save files from the host application.
|
||||
*/
|
||||
|
@ -46,7 +46,7 @@ export class AutoRest extends EventEmitter {
|
|||
* @param content - the file content to evaluate
|
||||
*/
|
||||
public static async IsSwaggerFile(content: string): Promise<boolean> {
|
||||
// this checks to see if the document is a swagger document
|
||||
// this checks to see if the document is a swagger document
|
||||
try {
|
||||
// quick check to see if it's json already
|
||||
let doc = JSON.parse(content);
|
||||
|
@ -120,8 +120,8 @@ export class AutoRest extends EventEmitter {
|
|||
}
|
||||
}
|
||||
|
||||
public AddConfiguration(configuratuion: any): void {
|
||||
this._configurations.push(configuratuion);
|
||||
public AddConfiguration(configuration: any): void {
|
||||
Push(this._configurations, configuration);
|
||||
this.Invalidate();
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ export class AutoRest extends EventEmitter {
|
|||
}
|
||||
|
||||
public get HasConfiguration(): Promise<boolean> {
|
||||
return new Promise(async (r, f) => {
|
||||
return new Promise<boolean>(async (r, f) => {
|
||||
(await this.view);
|
||||
r(false);
|
||||
});
|
||||
|
@ -166,8 +166,6 @@ export class AutoRest extends EventEmitter {
|
|||
return false;
|
||||
}
|
||||
|
||||
this.Message.Dispatch({ Channel: Channel.Debug, Text: `Starting Process() Run Pipeline.` });
|
||||
|
||||
if (view.InputFileUris.length === 0) {
|
||||
throw new Exception("No input files provided.\n\nUse --help to get help information.", 0);
|
||||
}
|
||||
|
@ -215,7 +213,7 @@ export class AutoRest extends EventEmitter {
|
|||
@EventEmitter.Event public Finished: IEvent<AutoRest, boolean | Error>;
|
||||
|
||||
/**
|
||||
* Event: Signals when a File is generated
|
||||
* Event: Signals when a File is generated
|
||||
*/
|
||||
@EventEmitter.Event public GeneratedFile: IEvent<AutoRest, Artifact>;
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,7 @@ import { OperationAbortedException } from "./exception";
|
|||
import { TryDecodeEnhancedPositionFromName } from "./source-map/source-map";
|
||||
import { Supressor } from "./pipeline/supression";
|
||||
import { matches, stringify } from "./ref/jsonpath";
|
||||
import { MergeOverwriteOrAppend } from "./source-map/merging";
|
||||
import { MergeOverwriteOrAppend, resolveRValue, ShallowCopy } from "./source-map/merging";
|
||||
import { DataHandleRead, DataStore } from './data-store/data-store';
|
||||
import { EventEmitter, IEvent } from "./events";
|
||||
import { CodeBlock, EvaluateGuard, ParseCodeBlocks } from "./parsing/literate-yaml";
|
||||
|
@ -19,6 +19,8 @@ import { Channel, Message, SourceLocation, Range } from "./message";
|
|||
import { Artifact } from "./artifact";
|
||||
import { CancellationTokenSource, CancellationToken } from "./ref/cancallation";
|
||||
|
||||
const RESOLVE_MACROS_AT_RUNTIME = true;
|
||||
|
||||
export interface AutoRestConfigurationImpl {
|
||||
__info?: string | null;
|
||||
"input-file": string[] | string;
|
||||
|
@ -28,6 +30,9 @@ export interface AutoRestConfigurationImpl {
|
|||
"message-format"?: "json";
|
||||
"vscode"?: any; // activates VS Code specific behavior and does *NOT* influence the core's behavior (only consumed by VS Code extension)
|
||||
|
||||
"debug"?: boolean;
|
||||
"verbose"?: boolean;
|
||||
|
||||
// plugin specific
|
||||
"output-file"?: string;
|
||||
"output-folder"?: string;
|
||||
|
@ -50,25 +55,25 @@ export interface AutoRestConfigurationImpl {
|
|||
}
|
||||
|
||||
// TODO: operate on DataHandleRead and create source map!
|
||||
function MergeConfigurations(a: AutoRestConfigurationImpl, b: AutoRestConfigurationImpl): AutoRestConfigurationImpl {
|
||||
function MergeConfigurations(higherPriority: AutoRestConfigurationImpl, lowerPriority: AutoRestConfigurationImpl): AutoRestConfigurationImpl {
|
||||
// check guard
|
||||
if (b.__info && !EvaluateGuard(b.__info, a)) {
|
||||
if (lowerPriority.__info && !EvaluateGuard(lowerPriority.__info, higherPriority)) {
|
||||
// guard false? => skip
|
||||
return a;
|
||||
return higherPriority;
|
||||
}
|
||||
|
||||
// merge
|
||||
return MergeOverwriteOrAppend(a, b);
|
||||
return MergeOverwriteOrAppend(higherPriority, lowerPriority);
|
||||
}
|
||||
|
||||
function ValuesOf<T>(obj: any): Iterable<T> {
|
||||
if (obj === undefined) {
|
||||
function ValuesOf<T>(value: any): Iterable<T> {
|
||||
if (value === undefined) {
|
||||
return [];
|
||||
}
|
||||
if (obj instanceof Array) {
|
||||
return obj;
|
||||
if (value instanceof Array) {
|
||||
return value;
|
||||
}
|
||||
return [obj];
|
||||
return [value];
|
||||
}
|
||||
|
||||
export interface Directive {
|
||||
|
@ -118,7 +123,7 @@ export class DirectiveView {
|
|||
|
||||
export class MessageEmitter extends EventEmitter {
|
||||
/**
|
||||
* Event: Signals when a File is generated
|
||||
* Event: Signals when a File is generated
|
||||
*/
|
||||
@EventEmitter.Event public GeneratedFile: IEvent<MessageEmitter, Artifact>;
|
||||
/**
|
||||
|
@ -137,7 +142,25 @@ export class MessageEmitter extends EventEmitter {
|
|||
/* @internal */ public get CancellationToken(): CancellationToken { return this.cancellationTokenSource.token; }
|
||||
}
|
||||
|
||||
function ProxifyConfigurationView(cfgView: any) {
|
||||
return new Proxy(cfgView, {
|
||||
get: (target, property) => {
|
||||
const value = (<any>target)[property];
|
||||
if (value && value instanceof Array) {
|
||||
const result = [];
|
||||
for (const each of value) {
|
||||
result.push(resolveRValue(each, "", target, null));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return resolveRValue(value, <string>property, null, cfgView);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export class ConfigurationView {
|
||||
[name: string]: any;
|
||||
|
||||
private suppressor: Supressor;
|
||||
|
||||
|
@ -147,34 +170,73 @@ export class ConfigurationView {
|
|||
...configs: Array<AutoRestConfigurationImpl> // decreasing priority
|
||||
) {
|
||||
|
||||
// TODO: fix configuration loading, note that there was no point in passing that DataStore used
|
||||
// TODO: fix configuration loading, note that there was no point in passing that DataStore used
|
||||
// for loading in here as all connection to the sources is lost when passing `Array<AutoRestConfigurationImpl>` instead of `DataHandleRead`s...
|
||||
// theoretically the `ValuesOf` approach and such won't support blaming (who to blame if $.directives[3] sucks? which code block was it from)
|
||||
// long term, we simply gotta write a `Merge` method that adheres to the rules we need in here.
|
||||
this.config = <any>{
|
||||
this.rawConfig = <any>{
|
||||
"directive": [],
|
||||
"input-file": [],
|
||||
"output-artifact": []
|
||||
"output-artifact": [],
|
||||
};
|
||||
|
||||
for (const config of configs) {
|
||||
this.config = MergeConfigurations(this.config, config);
|
||||
this.rawConfig = MergeConfigurations(this.rawConfig, config);
|
||||
}
|
||||
|
||||
// default values that are the least priority.
|
||||
this.rawConfig = MergeConfigurations(this.rawConfig, <any>{
|
||||
"base-folder": ".",
|
||||
"output-folder": "generated",
|
||||
"debug": false,
|
||||
"verbose": false,
|
||||
"disable-validation": false
|
||||
});
|
||||
|
||||
if (RESOLVE_MACROS_AT_RUNTIME) {
|
||||
// if RESOLVE_MACROS_AT_RUNTIME is set
|
||||
// this will insert a Proxy object in most of the uses of
|
||||
// the configuration, and will do a macro resolution when the
|
||||
// value is retrieved.
|
||||
|
||||
// I have turned on this behavior by default. I'm not sure that
|
||||
// I need it at this point, but I'm leaving this code here since
|
||||
// It's possible that I do.
|
||||
this.config = ProxifyConfigurationView(this.rawConfig);
|
||||
} else {
|
||||
this.config = this.rawConfig;
|
||||
}
|
||||
|
||||
this.suppressor = new Supressor(this);
|
||||
this.Message({ Channel: Channel.Debug, Text: `Creating ConfigurationView : ${configs.length} sections.` });
|
||||
}
|
||||
|
||||
/* @internal */ public get DataStore(): DataStore { return this.messageEmitter.DataStore; }
|
||||
|
||||
/* @internal */ public get CancellationToken(): CancellationToken { return this.messageEmitter.CancellationToken; }
|
||||
|
||||
/* @internal */ public get CancellationTokenSource(): CancellationTokenSource { return this.messageEmitter.CancellationTokenSource; }
|
||||
|
||||
/* @internal */ public get GeneratedFile(): IEvent<MessageEmitter, Artifact> {
|
||||
return this.messageEmitter.GeneratedFile;
|
||||
public get Keys(): Array<string> {
|
||||
return Object.getOwnPropertyNames(this.config);
|
||||
}
|
||||
|
||||
public Dump(title: string = "") {
|
||||
console.log(`\n${title}\n===================================`)
|
||||
for (const each of Object.getOwnPropertyNames(this.config)) {
|
||||
console.log(`${each} : ${(<any>this.config)[each]}`);
|
||||
};
|
||||
}
|
||||
|
||||
/* @internal */ public get Indexer(): ConfigurationView {
|
||||
return new Proxy<ConfigurationView>(this, {
|
||||
get: (target, property) => {
|
||||
return property in target.config ? (<any>target.config)[property] : this[property];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* @internal */ public get DataStore(): DataStore { return this.messageEmitter.DataStore; }
|
||||
/* @internal */ public get CancellationToken(): CancellationToken { return this.messageEmitter.CancellationToken; }
|
||||
/* @internal */ public get CancellationTokenSource(): CancellationTokenSource { return this.messageEmitter.CancellationTokenSource; }
|
||||
/* @internal */ public get GeneratedFile(): IEvent<MessageEmitter, Artifact> { return this.messageEmitter.GeneratedFile; }
|
||||
|
||||
private config: AutoRestConfigurationImpl;
|
||||
private rawConfig: AutoRestConfigurationImpl;
|
||||
|
||||
private ResolveAsFolder(path: string): string {
|
||||
return EnsureIsFolderUri(ResolveUri(this.BaseFolderUri, path));
|
||||
|
@ -185,7 +247,7 @@ export class ConfigurationView {
|
|||
}
|
||||
|
||||
private get BaseFolderUri(): string {
|
||||
return EnsureIsFolderUri(ResolveUri(this.configFileFolderUri, this.config["base-folder"] || "."));
|
||||
return EnsureIsFolderUri(ResolveUri(this.configFileFolderUri, this.config["base-folder"] as string));
|
||||
}
|
||||
|
||||
// public methods
|
||||
|
@ -202,7 +264,7 @@ export class ConfigurationView {
|
|||
}
|
||||
|
||||
public get OutputFolderUri(): string {
|
||||
return this.ResolveAsFolder(this.config["output-folder"] || "generated");
|
||||
return this.ResolveAsFolder(this.config["output-folder"] as string);
|
||||
}
|
||||
|
||||
public IsOutputArtifactRequested(artifact: string): boolean {
|
||||
|
@ -217,17 +279,32 @@ export class ConfigurationView {
|
|||
return this.config;
|
||||
}
|
||||
|
||||
public * GetPluginViews(pluginName: string): Iterable<ConfigurationView> {
|
||||
public get DebugMode(): boolean {
|
||||
return this.config["debug"] as boolean;
|
||||
}
|
||||
|
||||
public get VerboseMode(): boolean {
|
||||
return this.config["verbose"] as boolean;
|
||||
}
|
||||
|
||||
public * GetNestedConfiguration(pluginName: string): Iterable<ConfigurationView> {
|
||||
for (const section of ValuesOf<any>((this.config as any)[pluginName])) {
|
||||
if (section) {
|
||||
yield new ConfigurationView(this.messageEmitter, this.configFileFolderUri, section === true ? {} : section, this.config);
|
||||
yield new ConfigurationView(this.messageEmitter, this.configFileFolderUri, section === true ? {} : section, this.config).Indexer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// message pipeline (source map resolution, filter, ...)
|
||||
public Message(m: Message): void {
|
||||
this.messageEmitter.Message.Dispatch({ Channel: Channel.Debug, Text: `Incoming validation message (${m.Text}) - starting processing` });
|
||||
if (m.Channel === Channel.Debug && !this.DebugMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (m.Channel === Channel.Verbose && !this.VerboseMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// update source locations to point to loaded Swagger
|
||||
if (m.Source) {
|
||||
|
@ -323,10 +400,8 @@ export class ConfigurationView {
|
|||
this.messageEmitter.Message.Dispatch(mx);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.messageEmitter.Message.Dispatch({ Channel: Channel.Error, Text: `${e}` });
|
||||
}
|
||||
|
||||
this.messageEmitter.Message.Dispatch({ Channel: Channel.Debug, Text: `Incoming validation message (${m.Text}) - finished processing` });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -383,7 +458,7 @@ export class Configuration {
|
|||
configSegments.push(...blocks);
|
||||
}
|
||||
|
||||
return new ConfigurationView(messageEmitter, configFileFolderUri, ...configSegments);
|
||||
return new ConfigurationView(messageEmitter, configFileFolderUri, ...configSegments).Indexer;
|
||||
}
|
||||
|
||||
public constructor(
|
||||
|
@ -429,4 +504,4 @@ export class Configuration {
|
|||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
import * as marked from 'marked'
|
||||
import * as chalk from 'chalk'
|
||||
|
||||
import * as moment from 'moment';
|
||||
|
||||
const markedTerminal = require('marked-terminal')
|
||||
|
||||
marked.setOptions({
|
||||
renderer: new markedTerminal({
|
||||
heading: chalk.green.bold,
|
||||
firstHeading: chalk.green.bold,
|
||||
showSectionPrefix: false,
|
||||
strong: chalk.bold.blue,
|
||||
em: chalk.cyan,
|
||||
blockquote: chalk.yellow,
|
||||
tab: 2
|
||||
})
|
||||
})
|
||||
|
||||
export class Console {
|
||||
public static quiet: boolean = false;
|
||||
public static debug: boolean = false;
|
||||
public static verbose: boolean = false;
|
||||
|
||||
public static Log(text: any) {
|
||||
if (!this.quiet) {
|
||||
console.log(marked(`${text}`.trim()).trim());
|
||||
}
|
||||
}
|
||||
|
||||
private static get Timestamp(): string {
|
||||
const m = new Date();
|
||||
const hh = `${m.getHours()}`;
|
||||
const mm = `${m.getMinutes()}`;
|
||||
const ss = `${m.getSeconds()}`;
|
||||
|
||||
return chalk.red(`${chalk.gray(hh)}:${chalk.gray(mm)}:${chalk.gray(ss)}`);
|
||||
}
|
||||
|
||||
public static Debug(text: any) {
|
||||
if (this.debug) {
|
||||
console.log(chalk.bold.yellow(`[${this.Timestamp}] `) + marked(`${text}`.trim()).trim());
|
||||
}
|
||||
}
|
||||
|
||||
public static Verbose(text: any) {
|
||||
if (this.verbose) {
|
||||
console.log(chalk.bold.magenta(`[${this.Timestamp}] `) + marked(`${text}`.trim()).trim());
|
||||
}
|
||||
}
|
||||
|
||||
public static Error(text: any) {
|
||||
console.error(chalk.bold.red(`${text}`.trim()).trim());
|
||||
}
|
||||
|
||||
public static Exit(reason: any) {
|
||||
this.Error(reason || "Unknown Error");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
|
@ -61,13 +61,4 @@ export class RealFileSystem implements IFileSystem {
|
|||
async WriteFile(uri: string, content: string): Promise<void> {
|
||||
return WriteString(uri, content);
|
||||
}
|
||||
}
|
||||
|
||||
/// this stuff is to force __asyncValues to get emitted: see https://github.com/Microsoft/TypeScript/issues/14725
|
||||
async function* yieldFromMap(): AsyncIterable<string> {
|
||||
yield* ["hello", "world"];
|
||||
};
|
||||
async function foo() {
|
||||
for await (const each of yieldFromMap()) {
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ import { OperationAbortedException } from '../exception';
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Descendants, Kind, CloneAst, YAMLMapping, newScalar, ParseNode } from "../ref/yaml";
|
||||
import { MergeYamls, IdentitySourceMapping } from "../source-map/merging";
|
||||
import { MergeYamls, IdentitySourceMapping, resolveRValue } from "../source-map/merging";
|
||||
import { Mapping } from "../ref/source-map";
|
||||
import { DataHandleRead, DataHandleWrite, DataStoreView } from "../data-store/data-store";
|
||||
import { Parse as ParseLiterate } from "./literate";
|
||||
|
@ -264,7 +264,26 @@ async function ParseCodeBlocksInternal(config: ConfigurationView, hLiterate: Dat
|
|||
}
|
||||
|
||||
export function EvaluateGuard(rawFenceGuard: string, contextObject: any): boolean {
|
||||
const match = /\$\((.*)\)/.exec(rawFenceGuard);
|
||||
// trim the language from the front first
|
||||
let match = /^\S*\s*(.*)/.exec(rawFenceGuard);
|
||||
let fence = match && match[1];
|
||||
if (!fence) {
|
||||
// no fence at all.
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
const expressionFence = `${resolveRValue(fence, "", contextObject, null, 2)}`;
|
||||
// is there unresolved values? May be old-style, or not valid value yet.
|
||||
if (expressionFence.indexOf("$(") == -1) {
|
||||
return safeEval<boolean>(expressionFence);
|
||||
}
|
||||
} catch (E) {
|
||||
// not a legal expression?
|
||||
}
|
||||
|
||||
// fall back to original behavior, where the whole expression is in the $( ... )
|
||||
match = /\$\((.*)\)/.exec(fence);
|
||||
const guardExpression = match && match[1];
|
||||
if (!guardExpression) {
|
||||
return true;
|
||||
|
|
|
@ -177,7 +177,7 @@ function BuildPipeline(config: ConfigurationView): { pipeline: { [name: string]:
|
|||
const addNodesAndSuffixes = (suffix: string, inputs: string[], configScope: JsonPath, inputNodes: { name: string, suffixes: string[] }[]) => {
|
||||
if (inputNodes.length === 0) {
|
||||
const config = configCache[stringify(configScope)];
|
||||
const configs = scope ? [...config.GetPluginViews(scope)] : [config];
|
||||
const configs = scope ? [...config.GetNestedConfiguration(scope)] : [config];
|
||||
for (let i = 0; i < configs.length; ++i) {
|
||||
const newSuffix = configs.length === 1 ? "" : "/" + i;
|
||||
suffixes.push(suffix + newSuffix);
|
||||
|
@ -320,4 +320,4 @@ export async function RunPipeline(configView: ConfigurationView, fileSystem: IFi
|
|||
barrier.Await(getTask(name));
|
||||
}
|
||||
await barrier.Wait();
|
||||
}
|
||||
}
|
|
@ -5,6 +5,18 @@ return it(jt(this),t,arguments.length>1?arguments[1]:void 0)},forEach:function f
|
|||
if("root"===e.tryLoc)return handle("end");if(e.tryLoc<=this.prev){var u=i.call(e,"catchLoc"),c=i.call(e,"finallyLoc");if(u&&c){if(this.prev<e.catchLoc)return handle(e.catchLoc,!0);if(this.prev<e.finallyLoc)return handle(e.finallyLoc)}else if(u){if(this.prev<e.catchLoc)return handle(e.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<e.finallyLoc)return handle(e.finallyLoc)}}}},abrupt:function(t,n){for(var r=this.tryEntries.length-1;r>=0;--r){var e=this.tryEntries[r];if(e.tryLoc<=this.prev&&i.call(e,"finallyLoc")&&this.prev<e.finallyLoc){var o=e;break}}o&&("break"===t||"continue"===t)&&o.tryLoc<=n&&n<=o.finallyLoc&&(o=null);var u=o?o.completion:{};return u.type=t,u.arg=n,o?this.next=o.finallyLoc:this.complete(u),p},complete:function(t,n){if("throw"===t.type)throw t.arg;"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=t.arg,this.next="end"):"normal"===t.type&&n&&(this.next=n)},finish:function(t){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.finallyLoc===t)return this.complete(r.completion,r.afterLoc),resetTryEntry(r),p}},catch:function(t){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.tryLoc===t){var e=r.completion;if("throw"===e.type){var i=e.arg;resetTryEntry(r)}return i}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:values(t),resultName:n,nextLoc:r},p}}}("object"==typeof t?t:"object"==typeof window?window:"object"==typeof self?self:this)}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{}]},{},[1]);
|
||||
}
|
||||
|
||||
// to enable bluebird stack traces, set global.ENABLE_BLUEBIRD to true
|
||||
if (global.ENABLE_BLUEBIRD ) {
|
||||
const Promise = require("bluebird")
|
||||
Promise.config({
|
||||
longStackTraces: true,
|
||||
warnings: {
|
||||
wForgottenReturn: false
|
||||
}
|
||||
})
|
||||
|
||||
global.Promise = Promise;
|
||||
}
|
||||
if( !global.__awaiter ) {
|
||||
global.__awaiter = (thisArg, _arguments, P, generator) => new Promise((resolve, reject) => {
|
||||
var fulfilled = (value) => { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
|
@ -18,7 +30,7 @@ if( !global.__awaiter ) {
|
|||
return o = __asyncValues(o), i[Symbol.iterator] = function () { return this; }, i;
|
||||
function verb(n, f) { return function (v) { return { value: ["delegate", (o[n] || f).call(o, v)], done: false }; }; }
|
||||
};
|
||||
|
||||
|
||||
global.__asyncGenerator = function (thisArg, _arguments, generator) {
|
||||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||
var g = generator.apply(thisArg, _arguments || []), q = [], c, i;
|
||||
|
@ -32,13 +44,13 @@ if( !global.__awaiter ) {
|
|||
function reject(value) { resume("throw", value); }
|
||||
function settle(f, v) { c = void 0, f(v), next(); }
|
||||
};
|
||||
|
||||
|
||||
global.__asyncValues = function (o) {
|
||||
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
||||
var m = o[Symbol.asyncIterator];
|
||||
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
|
||||
};
|
||||
|
||||
|
||||
global.__decorate = function (decorators, target, key, desc) {
|
||||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||||
|
|
|
@ -11,4 +11,19 @@ export async function ToArray<T>(iterable: AsyncIterable<T>): Promise<Array<T>>
|
|||
result.push(each);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function Push<T>(destination: Array<T>, source: any) {
|
||||
if (source) {
|
||||
if (IsIterable(source)) {
|
||||
destination.push(...source);
|
||||
}
|
||||
else {
|
||||
destination.push(source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function IsIterable(target: any) {
|
||||
return target && target[Symbol.iterator] && typeof target !== 'string'
|
||||
}
|
|
@ -65,8 +65,91 @@ function Merge(a: any, b: any, path: JsonPath = []): any {
|
|||
throw new Error(`'${stringify(path)}' has incomaptible values (${yaml.Stringify(a)}, ${yaml.Stringify(b)}).`);
|
||||
}
|
||||
|
||||
export function ShallowCopy(input: any, ...filter: Array<string>): any {
|
||||
if (!input) {
|
||||
return input;
|
||||
}
|
||||
const keys = input.Keys ? input.Keys : Object.getOwnPropertyNames(input);
|
||||
|
||||
const result: any = {};
|
||||
for (const key of keys) {
|
||||
if (filter.indexOf(key) == -1) {
|
||||
const value = input[key];
|
||||
if (value !== undefined) {
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Note: I am not convinced this works precisely as it should
|
||||
// but it works well enough for my needs right now
|
||||
// I will revisit it later.
|
||||
const macroRegEx = /\$\(([a-zA-Z0-9_-]*)\)/ig
|
||||
export function resolveRValue(value: any, propertyName: string, higherPriority: any, lowerPriority: any, jsAware: number = 0): any {
|
||||
if (value) {
|
||||
// resolves the actual macro value.
|
||||
const resolve = (macroExpression: string, macroKey: string) => {
|
||||
// if the original set has it, use that.
|
||||
if (higherPriority && higherPriority[macroKey]) {
|
||||
return resolveRValue(higherPriority[macroKey], macroKey, lowerPriority, null, jsAware - 1);
|
||||
}
|
||||
|
||||
if (lowerPriority) {
|
||||
// check to see if the value is in the overrides set before the key itself.
|
||||
const keys = Object.getOwnPropertyNames(lowerPriority);
|
||||
const macroKeyLocation = keys.indexOf(macroKey);
|
||||
if (macroKeyLocation > -1) {
|
||||
if (macroKeyLocation < keys.indexOf(propertyName)) {
|
||||
// the macroKey is in the overrides, and it precedes the propertyName itself
|
||||
return resolveRValue(lowerPriority[macroKey], macroKey, higherPriority, lowerPriority, jsAware - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// can't find the macro. maybe later.
|
||||
return macroExpression;
|
||||
};
|
||||
|
||||
// resolve the macro value for strings
|
||||
if (typeof value === "string") {
|
||||
const match = macroRegEx.exec(value.trim());
|
||||
if (match) {
|
||||
if (match[0] === match.input) {
|
||||
// the target value should be the result without string twiddling
|
||||
if (jsAware > 0) {
|
||||
return `'${resolve(match[0], match[1])}'`;
|
||||
}
|
||||
return resolve(match[0], match[1]);
|
||||
}
|
||||
// it looks like we should do a string replace.
|
||||
return value.replace(macroRegEx, resolve)
|
||||
}
|
||||
}
|
||||
|
||||
// resolve macro values for array values
|
||||
if (value instanceof Array) {
|
||||
const result = [];
|
||||
for (const each of value) {
|
||||
// since we're not naming the parameter,
|
||||
// if there isn't a higher priority,
|
||||
// we can fall back to a wide-lookup in lowerPriority.
|
||||
result.push(resolveRValue(each, "", higherPriority || lowerPriority, null));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (jsAware > 0) {
|
||||
return `'${value}'`;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
export function MergeOverwriteOrAppend(a: any, b: any, concatListPathFilter: (path: JsonPath) => boolean = _ => false, path: JsonPath = []): any {
|
||||
if (a === null || b == null) {
|
||||
if (a === null || b === null) {
|
||||
return null; // TODO: overthink, we could use this to force mute something even if it's "concat" mode...
|
||||
}
|
||||
|
||||
|
@ -91,17 +174,17 @@ export function MergeOverwriteOrAppend(a: any, b: any, concatListPathFilter: (pa
|
|||
|
||||
// forward if only present in one of the nodes
|
||||
if (a[key] === undefined) {
|
||||
result[key] = b[key];
|
||||
result[key] = resolveRValue(b[key], key, a, b);
|
||||
continue;
|
||||
}
|
||||
if (b[key] === undefined) {
|
||||
result[key] = a[key];
|
||||
result[key] = resolveRValue(a[key], key, null, a);
|
||||
continue;
|
||||
}
|
||||
|
||||
// try merge objects otherwise
|
||||
const aMember = a[key];
|
||||
const bMember = b[key];
|
||||
const aMember = resolveRValue(a[key], key, b, a);
|
||||
const bMember = resolveRValue(b[key], key, a, b);
|
||||
result[key] = MergeOverwriteOrAppend(aMember, bMember, concatListPathFilter, subpath);
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -21,16 +21,22 @@
|
|||
},
|
||||
"typings": "./index.d.ts",
|
||||
"devDependencies": {
|
||||
"@types/chalk": "*",
|
||||
"@types/marked": "*",
|
||||
"@types/commonmark": "^0.22.29",
|
||||
"@types/jsonpath": "^0.1.29",
|
||||
"@types/pify": "0.0.28",
|
||||
"@types/source-map": "^0.5.0",
|
||||
"bluebird": "*",
|
||||
"mocha": "3.2.0",
|
||||
"mocha-typescript": "1.0.22",
|
||||
"source-map-support": "^0.4.14",
|
||||
"typescript": "^2.3.0-dev.20170314"
|
||||
},
|
||||
"dependencies": {
|
||||
"chalk": "^1.1.2",
|
||||
"marked": "^0.3.6",
|
||||
"marked-terminal": "^2.0.0",
|
||||
"commonmark": "^0.27.0",
|
||||
"file-url": "^2.0.2",
|
||||
"get-uri": "^2.0.0",
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
// polyfills for language support
|
||||
require("../lib/polyfill.min.js");
|
||||
|
||||
import { suite, test, slow, timeout, skip, only } from "mocha-typescript";
|
||||
import * as assert from "assert";
|
||||
import { IFileSystem, MemoryFileSystem } from "../lib/file-system"
|
||||
import * as AutoRest from "../lib/autorest-core"
|
||||
|
||||
@suite class TestConfiguration {
|
||||
|
||||
@test async "Test config"() {
|
||||
// test out subscribe
|
||||
|
||||
let f = new MemoryFileSystem(new Map<string, string>([
|
||||
['readme.md', `
|
||||
# this is a test
|
||||
see https://aka.ms/autorest
|
||||
~~~ yaml
|
||||
my-value: $(sample-value)
|
||||
sample-value: one
|
||||
sample-other: $(sample-value)
|
||||
|
||||
input-file:
|
||||
- other.md
|
||||
|
||||
items:
|
||||
- foo
|
||||
- bar
|
||||
- bin
|
||||
- $(sample-value)/two
|
||||
|
||||
output-folder: foo
|
||||
|
||||
csharp:
|
||||
sample-value: two
|
||||
output-folder: $(output-folder)/csharp
|
||||
|
||||
~~~
|
||||
`],
|
||||
['other.md', `
|
||||
# My Doc.
|
||||
|
||||
# some text
|
||||
|
||||
`]]));
|
||||
|
||||
const autorest = new AutoRest.AutoRest(f, MemoryFileSystem.DefaultVirtualRootUri + "readme.md");
|
||||
let cfg = await autorest.view;
|
||||
|
||||
// console.log(cfg.Raw);
|
||||
|
||||
// output folder should be 'foo'
|
||||
assert.equal(cfg['output-folder'], "foo");
|
||||
|
||||
// my-value should not get resolved here because the dependent variable is after
|
||||
assert.equal(cfg['my-value'], '$(sample-value)');
|
||||
|
||||
// sample-other should get resolved to the value of sample-value
|
||||
assert.equal(cfg['sample-other'], 'one');
|
||||
|
||||
// verify that the items object that uses a macro works too
|
||||
assert.equal(cfg['items'][3], "one/two");
|
||||
|
||||
for (const each of cfg.GetNestedConfiguration("csharp")) {
|
||||
// console.log(each.Raw);
|
||||
|
||||
// verify the output folder is relative
|
||||
assert.equal(each.GetEntry('output-folder'), "foo/csharp");
|
||||
|
||||
// verify that the items object that uses a macro works too
|
||||
// assert.equal((<any>(each.Raw))['items'][3], "two/two");
|
||||
|
||||
// now, this got resolved alot earlier.
|
||||
// dunno if we need it the other way or not.
|
||||
assert.equal(each['items'][3], "one/two");
|
||||
}
|
||||
|
||||
// override the output-folder from the cmdline
|
||||
autorest.AddConfiguration({ "output-folder": "OUTPUT" });
|
||||
cfg = await autorest.view;
|
||||
assert.equal(cfg['output-folder'], "OUTPUT");
|
||||
|
||||
for (const each of cfg.GetNestedConfiguration("csharp")) {
|
||||
assert.equal(each['output-folder'], "OUTPUT/csharp");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "autorest",
|
||||
"version": "0.13.1",
|
||||
"version": "0.13.2",
|
||||
"description": "The AutoRest tool generates client libraries for accessing RESTful web services. Input to AutoRest is a spec that describes the REST API using the Open API Initiative format.",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -117,42 +117,6 @@
|
|||
],
|
||||
"description": "An alert rule."
|
||||
},
|
||||
"LocationThresholdRuleCondition": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dataSource": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RuleDataSource"
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
],
|
||||
"description": "the resource from which the rule collects its data."
|
||||
},
|
||||
"windowSize": {
|
||||
"type": "string",
|
||||
"format": "duration",
|
||||
"description": "the period of time (in ISO 8601 duration format) that is used to monitor alert activity based on the threshold. If specified then it must be between 5 minutes and 1 day."
|
||||
},
|
||||
"failedLocationCount": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
],
|
||||
"description": "the number of locations that must fail to activate the alert."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"failedLocationCount"
|
||||
],
|
||||
"description": "A rule condition based on a certain number of locations failing."
|
||||
},
|
||||
"ManagementEventAggregationCondition": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -192,7 +156,43 @@
|
|||
},
|
||||
"description": "A management event aggregation condition."
|
||||
},
|
||||
"ManagementEventRuleCondition": {
|
||||
"Microsoft.Azure.Management.Insights.Models.LocationThresholdRuleCondition": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dataSource": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RuleDataSource"
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
],
|
||||
"description": "the resource from which the rule collects its data."
|
||||
},
|
||||
"windowSize": {
|
||||
"type": "string",
|
||||
"format": "duration",
|
||||
"description": "the period of time (in ISO 8601 duration format) that is used to monitor alert activity based on the threshold. If specified then it must be between 5 minutes and 1 day."
|
||||
},
|
||||
"failedLocationCount": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
],
|
||||
"description": "the number of locations that must fail to activate the alert."
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"failedLocationCount"
|
||||
],
|
||||
"description": "A rule condition based on a certain number of locations failing."
|
||||
},
|
||||
"Microsoft.Azure.Management.Insights.Models.ManagementEventRuleCondition": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dataSource": {
|
||||
|
@ -220,113 +220,7 @@
|
|||
},
|
||||
"description": "A management event rule condition."
|
||||
},
|
||||
"RuleAction": {
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"odata.type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleWebhookAction"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RuleEmailAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/RuleWebhookAction"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "The action that is performed when the alert rule becomes active, and when an alert condition is resolved."
|
||||
},
|
||||
"RuleCondition": {
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"odata.type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
|
||||
"Microsoft.Azure.Management.Insights.Models.LocationThresholdRuleCondition",
|
||||
"Microsoft.Azure.Management.Insights.Models.ManagementEventRuleCondition"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/ThresholdRuleCondition"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/LocationThresholdRuleCondition"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/ManagementEventRuleCondition"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "The condition that results in the alert rule being activated."
|
||||
},
|
||||
"RuleDataSource": {
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"odata.type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleManagementEventDataSource"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/RuleMetricDataSource"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/RuleManagementEventDataSource"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "The resource from which the rule collects its data."
|
||||
},
|
||||
"RuleEmailAction": {
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleEmailAction": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"sendToServiceOwners": {
|
||||
|
@ -357,17 +251,7 @@
|
|||
},
|
||||
"description": "Specifies the action to send email when the rule condition is evaluated."
|
||||
},
|
||||
"RuleManagementEventClaimsDataSource": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"emailAddress": {
|
||||
"type": "string",
|
||||
"description": "the email address."
|
||||
}
|
||||
},
|
||||
"description": "The claims for a rule management event data source."
|
||||
},
|
||||
"RuleManagementEventDataSource": {
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleManagementEventDataSource": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"eventName": {
|
||||
|
@ -420,7 +304,7 @@
|
|||
},
|
||||
"description": "A rule management event data source."
|
||||
},
|
||||
"RuleMetricDataSource": {
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"resourceUri": {
|
||||
|
@ -434,7 +318,7 @@
|
|||
},
|
||||
"description": "A rule metric data source."
|
||||
},
|
||||
"RuleWebhookAction": {
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleWebhookAction": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"serviceUri": {
|
||||
|
@ -458,7 +342,7 @@
|
|||
},
|
||||
"description": "Specifies the action to post to service when the rule condition is evaluated."
|
||||
},
|
||||
"ThresholdRuleCondition": {
|
||||
"Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"dataSource": {
|
||||
|
@ -529,6 +413,122 @@
|
|||
"threshold"
|
||||
],
|
||||
"description": "A rule condition based on a metric crossing a threshold."
|
||||
},
|
||||
"RuleAction": {
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"odata.type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleEmailAction",
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleWebhookAction"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Microsoft.Azure.Management.Insights.Models.RuleEmailAction"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/Microsoft.Azure.Management.Insights.Models.RuleWebhookAction"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "The action that is performed when the alert rule becomes active, and when an alert condition is resolved."
|
||||
},
|
||||
"RuleCondition": {
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"odata.type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition",
|
||||
"Microsoft.Azure.Management.Insights.Models.LocationThresholdRuleCondition",
|
||||
"Microsoft.Azure.Management.Insights.Models.ManagementEventRuleCondition"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Microsoft.Azure.Management.Insights.Models.ThresholdRuleCondition"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/Microsoft.Azure.Management.Insights.Models.LocationThresholdRuleCondition"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/Microsoft.Azure.Management.Insights.Models.ManagementEventRuleCondition"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "The condition that results in the alert rule being activated."
|
||||
},
|
||||
"RuleDataSource": {
|
||||
"type": "object",
|
||||
"allOf": [
|
||||
{
|
||||
"properties": {
|
||||
"odata.type": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource",
|
||||
"Microsoft.Azure.Management.Insights.Models.RuleManagementEventDataSource"
|
||||
]
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/Microsoft.Azure.Management.Insights.Models.RuleMetricDataSource"
|
||||
},
|
||||
{
|
||||
"$ref": "#/definitions/Microsoft.Azure.Management.Insights.Models.RuleManagementEventDataSource"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "The resource from which the rule collects its data."
|
||||
},
|
||||
"RuleManagementEventClaimsDataSource": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"emailAddress": {
|
||||
"type": "string",
|
||||
"description": "the email address."
|
||||
}
|
||||
},
|
||||
"description": "The claims for a rule management event data source."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -334,6 +334,23 @@
|
|||
},
|
||||
"description": "Sample input data for the service's input(s)."
|
||||
},
|
||||
"Graph": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"package": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/GraphPackage"
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
],
|
||||
"description": "The definition of the graph package making up this web service."
|
||||
}
|
||||
},
|
||||
"description": "Properties specific to a Graph based web service."
|
||||
},
|
||||
"GraphEdge": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -899,29 +916,12 @@
|
|||
{
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/WebServicePropertiesForGraph"
|
||||
"$ref": "#/definitions/Graph"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "The set of properties specific to the Azure ML web service resource."
|
||||
},
|
||||
"WebServicePropertiesForGraph": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"package": {
|
||||
"oneOf": [
|
||||
{
|
||||
"$ref": "#/definitions/GraphPackage"
|
||||
},
|
||||
{
|
||||
"$ref": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#/definitions/expression"
|
||||
}
|
||||
],
|
||||
"description": "The definition of the graph package making up this web service."
|
||||
}
|
||||
},
|
||||
"description": "Properties specific to a Graph based web service."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ namespace AutoRest.AzureResourceSchema
|
|||
resNameParam = resNameParam.Trim(new[] { '{', '}' });
|
||||
|
||||
// look up the type
|
||||
var param = method.Parameters.Where(p => p.Name == resNameParam).FirstOrDefault();
|
||||
var param = method.Parameters.Where(p => p.SerializedName == resNameParam).FirstOrDefault();
|
||||
if (param != null)
|
||||
{
|
||||
// create a schema for it
|
||||
|
@ -116,12 +116,12 @@ namespace AutoRest.AzureResourceSchema
|
|||
{
|
||||
foreach (Property property in body.ComposedProperties)
|
||||
{
|
||||
if (!resourceDefinition.Properties.Keys.Contains(property.Name.RawValue))
|
||||
if (!resourceDefinition.Properties.Keys.Contains(property.SerializedName))
|
||||
{
|
||||
JsonSchema propertyDefinition = ParseType(property, property.ModelType, resourceSchema.Definitions, serviceClient.ModelTypes);
|
||||
if (propertyDefinition != null)
|
||||
{
|
||||
resourceDefinition.AddProperty(property.Name.RawValue, propertyDefinition, property.IsRequired || property.Name.RawValue == "properties");
|
||||
resourceDefinition.AddProperty(property.SerializedName, propertyDefinition, property.IsRequired || property.SerializedName == "properties");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ namespace AutoRest.AzureResourceSchema
|
|||
if (IsPathVariable(pathSegment))
|
||||
{
|
||||
string parameterName = pathSegment.Substring(1, pathSegment.Length - 2);
|
||||
Parameter parameter = method.Parameters.FirstOrDefault(methodParameter => methodParameter.Name.RawValue == parameterName);
|
||||
Parameter parameter = method.Parameters.FirstOrDefault(methodParameter => methodParameter.SerializedName == parameterName);
|
||||
if (parameter == null)
|
||||
{
|
||||
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "Found undefined parameter reference {0} in create resource method \"{1}/{2}/{3}\".", pathSegment, resourceMethodPrefix, resourceProvider, methodUrlPathAfterProvider));
|
||||
|
@ -238,7 +238,7 @@ namespace AutoRest.AzureResourceSchema
|
|||
{
|
||||
foreach (EnumValue parameterValue in parameterType.Values)
|
||||
{
|
||||
newResourceTypes.Add(string.Join("/", resourceType, parameterValue.Name));
|
||||
newResourceTypes.Add(string.Join("/", resourceType, parameterValue.SerializedName));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,7 +319,7 @@ namespace AutoRest.AzureResourceSchema
|
|||
|
||||
private static JsonSchema ParseCompositeType(Property property, CompositeType compositeType, bool includeBaseModelTypeProperties, IDictionary<string, JsonSchema> definitions, IEnumerable<CompositeType> modelTypes)
|
||||
{
|
||||
string definitionName = compositeType.Name.RawValue;
|
||||
string definitionName = compositeType.SerializedName;
|
||||
|
||||
if (!definitions.ContainsKey(definitionName))
|
||||
{
|
||||
|
@ -368,7 +368,7 @@ namespace AutoRest.AzureResourceSchema
|
|||
|
||||
derivedTypeDefinitionRefs.AddAnyOf(new JsonSchema()
|
||||
{
|
||||
Ref = "#/definitions/" + subType.Name,
|
||||
Ref = "#/definitions/" + subType.SerializedName,
|
||||
});
|
||||
|
||||
const string discriminatorValueExtensionName = "x-ms-discriminator-value";
|
||||
|
@ -395,7 +395,7 @@ namespace AutoRest.AzureResourceSchema
|
|||
JsonSchema subPropertyDefinition = ParseType(subProperty, subProperty.ModelType, definitions, modelTypes);
|
||||
if (subPropertyDefinition != null)
|
||||
{
|
||||
baseTypeDefinition.AddProperty(subProperty.Name.RawValue, subPropertyDefinition, subProperty.IsRequired);
|
||||
baseTypeDefinition.AddProperty(subProperty.SerializedName.Else(subProperty.Name.RawValue) , subPropertyDefinition, subProperty.IsRequired);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -438,7 +438,7 @@ namespace AutoRest.AzureResourceSchema
|
|||
|
||||
foreach (EnumValue enumValue in enumType.Values)
|
||||
{
|
||||
result.AddEnum(enumValue.Name);
|
||||
result.AddEnum(enumValue.SerializedName);
|
||||
}
|
||||
|
||||
if (property != null)
|
||||
|
|
Загрузка…
Ссылка в новой задаче