зеркало из https://github.com/Azure/autorest.git
various goodness (#2263)
* stack trace crunching * add azure-openapi-validator * nail version * artificial order * make all external tools consume abs. URI * make everything consume absolute URIs * cleanup * ai * fixed that exit code * slightly improved samples * silence * cleanup * more cleanup * reboust silence * rem dependency
This commit is contained in:
Родитель
f547506b80
Коммит
a4603ff40f
|
@ -14,7 +14,9 @@ input-file:
|
|||
This time, we not only want to generate code, we also want to validate.
|
||||
|
||||
``` yaml
|
||||
azure-arm: true # enables validation messages
|
||||
azure-validator: true # Azure specific validation
|
||||
model-validator: true # validation of examples against the API definition
|
||||
semantic-validator: true # general semantic checks such as: Does the specified `default` value actually have the type specified for the corresponding field?
|
||||
```
|
||||
|
||||
## Generation
|
||||
|
@ -22,6 +24,7 @@ azure-arm: true # enables validation messages
|
|||
Also generate for some languages.
|
||||
|
||||
``` yaml
|
||||
azure-arm: true # generate code using Azure ARM flavor
|
||||
csharp:
|
||||
output-folder: CSharp
|
||||
java:
|
||||
|
|
|
@ -1 +1 @@
|
|||
0
|
||||
11
|
|
@ -12,7 +12,7 @@ input-file:
|
|||
## Validation
|
||||
|
||||
``` yaml
|
||||
azure-arm: true
|
||||
azure-validator: true
|
||||
```
|
||||
|
||||
## Suppression
|
||||
|
|
|
@ -1 +1 @@
|
|||
0
|
||||
11
|
|
@ -1 +1 @@
|
|||
0
|
||||
7
|
|
@ -51,6 +51,20 @@ swagger-document/individual/azure-validator:
|
|||
- azure-validator-individual
|
||||
inputs:
|
||||
- swagger-document/individual/transform
|
||||
swagger-document/azure-openapi-validator:
|
||||
pluginName: azure-openapi-validator
|
||||
configScope:
|
||||
- azure-validator-composed
|
||||
inputs:
|
||||
- swagger-document/transform
|
||||
- swagger-document/azure-validator
|
||||
swagger-document/individual/azure-openapi-validator:
|
||||
pluginName: azure-openapi-validator
|
||||
configScope:
|
||||
- azure-validator-individual
|
||||
inputs:
|
||||
- swagger-document/individual/transform
|
||||
- swagger-document/individual/azure-validator
|
||||
csharp/modeler:
|
||||
pluginName: modeler
|
||||
configScope:
|
||||
|
|
|
@ -1 +1 @@
|
|||
0
|
||||
11
|
|
@ -1 +1 @@
|
|||
0
|
||||
1
|
|
@ -1,10 +1,3 @@
|
|||
Error occurred. Exiting.
|
||||
{ Error: Error occurred. Exiting.
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
|
|
|
@ -1 +1 @@
|
|||
0
|
||||
1
|
|
@ -2,8 +2,3 @@ Process() Cancelled due to exception : Error occurred. Exiting.
|
|||
Error occurred. Exiting.
|
||||
{ Error: Error occurred. Exiting.
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
|
|
|
@ -2,7 +2,3 @@ Process() Cancelled due to exception : Error occurred. Exiting.
|
|||
Error occurred. Exiting.
|
||||
{ Error: Error occurred. Exiting.
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
|
|
|
@ -1,23 +1,7 @@
|
|||
FATAL: System.ArgumentException: Reference path 'Cowball' does not exist in the definition section of the Swagger document.
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
--- End of stack trace from previous location where exception was thrown ---
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
FATAL: csharp/modeler - FAILED
|
||||
Error: Plugin modeler reported failure.
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
at ...
|
||||
|
|
|
@ -1 +1 @@
|
|||
0
|
||||
4
|
|
@ -456,7 +456,7 @@ async function main() {
|
|||
// for relaxed profiling (assuming that no one calls `main` from electron... use AAAL!)
|
||||
if (require("process").versions.electron) await new Promise(_ => { });
|
||||
|
||||
process.exit(0);
|
||||
process.exit(exitcode);
|
||||
} catch (e) {
|
||||
if (e instanceof Exception) {
|
||||
console.log(e.message);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
require("./lib/polyfill.min.js");
|
||||
export { IFileSystem } from "./lib/file-system"
|
||||
export { Message, Channel } from "./lib/message"
|
||||
|
|
|
@ -3,9 +3,8 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as path from "path";
|
||||
import { ResolveUri, GetFilenameWithoutExtension } from "./lib/ref/uri";
|
||||
import { DataHandleRead, DataStoreViewReadonly } from "./lib/data-store/data-store";
|
||||
import { DataStoreViewReadonly } from "./lib/data-store/data-store";
|
||||
import { AutoRestConfigurationImpl } from "./lib/configuration";
|
||||
|
||||
const regexLegacyArg = /^-[^-]/;
|
||||
|
@ -60,7 +59,7 @@ export async function CreateConfiguration(baseFolderUri: string, inputScope: Dat
|
|||
const codegenerator = switches["g"] || switches["codegenerator"] || "CSharp";
|
||||
const usedCodeGenerator = codegenerator.toLowerCase().replace("azure.", "").replace(".fluent", "");
|
||||
if (codegenerator.toLowerCase() === "none") {
|
||||
result["azure-validator"] = true;
|
||||
(<any>result)["azure-validator"] = true;
|
||||
} else {
|
||||
(<any>result)[usedCodeGenerator] = {};
|
||||
if (codegenerator.toLowerCase().startsWith("azure.")) {
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
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, Push } from './ref/linq';
|
||||
import { IEvent, EventDispatcher, EventEmitter } from "./events";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { RunPipeline } from "./pipeline/pipeline";
|
||||
import { Push } from "./ref/linq";
|
||||
import { IEvent, EventEmitter } from "./events";
|
||||
import { IFileSystem } from "./file-system";
|
||||
import { Configuration, ConfigurationView, MessageEmitter } from './configuration';
|
||||
import { DocumentType } from "./document-type";
|
||||
export { ConfigurationView } from './configuration';
|
||||
import { Message, Channel } from './message';
|
||||
import * as Constants from './constants';
|
||||
import { Artifact } from './artifact';
|
||||
import { Exception, OperationCanceledException } from './exception';
|
||||
import { Configuration, ConfigurationView, MessageEmitter } from "./configuration";
|
||||
export { ConfigurationView } from "./configuration";
|
||||
import { Message, Channel } from "./message";
|
||||
import * as Constants from "./constants";
|
||||
import { Artifact } from "./artifact";
|
||||
|
||||
export class AutoRest extends EventEmitter {
|
||||
private _configurations = new Array<any>();
|
||||
|
@ -167,9 +167,14 @@ export class AutoRest extends EventEmitter {
|
|||
}
|
||||
|
||||
if (view.InputFileUris.length === 0) {
|
||||
throw new Exception("No input files provided.\n\nUse --help to get help information.", 0);
|
||||
if (view.GetEntry("allow-no-input")) {
|
||||
return true;
|
||||
} else {
|
||||
return new Error("No input files provided.\n\nUse --help to get help information.");
|
||||
}
|
||||
}
|
||||
const result = await Promise.race([
|
||||
|
||||
await Promise.race([
|
||||
RunPipeline(view, <IFileSystem>this.fileSystem),
|
||||
new Promise((_, rej) => view.CancellationToken.onCancellationRequested(() => rej("Cancellation requested.")))]);
|
||||
|
||||
|
@ -178,8 +183,7 @@ export class AutoRest extends EventEmitter {
|
|||
|
||||
view.messageEmitter.removeAllListeners();
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
/* if (!(e instanceof OperationCanceledException)) {
|
||||
console.error(e.message);
|
||||
|
|
|
@ -4,16 +4,15 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { BlameTree } from "./source-map/blaming";
|
||||
import { Clone } from "./ref/yaml";
|
||||
import { OperationAbortedException } from "./exception";
|
||||
import { TryDecodeEnhancedPositionFromName } from "./source-map/source-map";
|
||||
import { Suppressor } from "./pipeline/suppression";
|
||||
import { matches, stringify } from "./ref/jsonpath";
|
||||
import { MergeOverwriteOrAppend, resolveRValue, ShallowCopy } from "./source-map/merging";
|
||||
import { stringify } from "./ref/jsonpath";
|
||||
import { MergeOverwriteOrAppend, resolveRValue } 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";
|
||||
import { CreateFolderUri, EnsureIsFolderUri, ReadUri, ResolveUri } from "./ref/uri";
|
||||
import { EvaluateGuard, ParseCodeBlocks } from "./parsing/literate-yaml";
|
||||
import { CreateFolderUri, EnsureIsFolderUri, ResolveUri } from "./ref/uri";
|
||||
import { From } from "./ref/linq";
|
||||
import { IFileSystem } from "./file-system";
|
||||
import * as Constants from "./constants";
|
||||
|
@ -25,6 +24,7 @@ const RESOLVE_MACROS_AT_RUNTIME = true;
|
|||
|
||||
export interface AutoRestConfigurationImpl {
|
||||
__info?: string | null;
|
||||
"allow-no-input"?: boolean;
|
||||
"input-file": string[] | string;
|
||||
"base-folder"?: string;
|
||||
"directive"?: Directive[] | Directive;
|
||||
|
@ -43,11 +43,8 @@ export interface AutoRestConfigurationImpl {
|
|||
"client-side-validation"?: boolean; // C#
|
||||
"fluent"?: boolean;
|
||||
"azure-arm"?: boolean;
|
||||
"azure-validator"?: boolean;
|
||||
"model-validator"?: boolean;
|
||||
"semantic-validator"?: boolean;
|
||||
"override-info"?: any; // make sure source maps are pulling it! (see "composite swagger" method)
|
||||
"namespace"?: string; // TODO: the modeler cares :( because it is badly designed
|
||||
"namespace"?: string;
|
||||
"license-header"?: string;
|
||||
"add-credentials"?: boolean;
|
||||
"package-name"?: string; // Ruby, Python, ...
|
||||
|
@ -188,6 +185,7 @@ export class ConfigurationView {
|
|||
}
|
||||
|
||||
// default values that are the least priority.
|
||||
// TODO: why is this here and not in default-configuration?
|
||||
this.rawConfig = MergeConfigurations(this.rawConfig, <any>{
|
||||
"base-folder": ".",
|
||||
"output-folder": "generated",
|
||||
|
@ -275,7 +273,11 @@ export class ConfigurationView {
|
|||
}
|
||||
|
||||
public GetEntry(key: keyof AutoRestConfigurationImpl): any {
|
||||
return (this.config as any)[key];
|
||||
let result = this.config as any;
|
||||
for (const keyPart of key.split(".")) {
|
||||
result = result[keyPart];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public get Raw(): AutoRestConfigurationImpl {
|
||||
|
@ -293,12 +295,12 @@ export class ConfigurationView {
|
|||
public * GetNestedConfiguration(pluginName: string): Iterable<ConfigurationView> {
|
||||
for (const section of ValuesOf<any>((this.config as any)[pluginName])) {
|
||||
if (section) {
|
||||
yield this.GetPluginViewImmediate(section === true ? {} : section);
|
||||
yield this.GetNestedConfigurationImmediate(section === true ? {} : section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GetPluginViewImmediate(...scope: any[]): ConfigurationView {
|
||||
public GetNestedConfigurationImmediate(...scope: any[]): ConfigurationView {
|
||||
return new ConfigurationView(this.messageEmitter, this.configFileFolderUri, ...scope, this.config).Indexer;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
import * as marked from 'marked'
|
||||
import * as chalk from 'chalk'
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as moment from 'moment';
|
||||
import * as marked from "marked";
|
||||
import * as chalk from "chalk";
|
||||
|
||||
const markedTerminal = require('marked-terminal')
|
||||
import * as moment from "moment";
|
||||
|
||||
const markedTerminal = require("marked-terminal");
|
||||
|
||||
marked.setOptions({
|
||||
renderer: new markedTerminal({
|
||||
|
@ -15,7 +20,7 @@ marked.setOptions({
|
|||
blockquote: chalk.yellow,
|
||||
tab: 2
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
export class Console {
|
||||
public static quiet: boolean = false;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export const MagicString: string = "\n> see https://aka.ms/autorest";
|
||||
export const DefaultConfiguratiion: string = "readme.md";
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
import { LineIndices } from "../parsing/text-utility";
|
||||
import { CancellationToken } from "../ref/cancallation";
|
||||
import { Mappings, Mapping, SmartPosition, Position } from "../ref/source-map";
|
||||
import { EnsureIsFolderUri, ReadUri, ResolveUri, WriteString } from '../ref/uri';
|
||||
import { FastStringify, Parse, ParseNode, ParseToAst as parseAst, Stringify, YAMLNode } from '../ref/yaml';
|
||||
import { EnsureIsFolderUri, ReadUri, ResolveUri, WriteString } from "../ref/uri";
|
||||
import { FastStringify, ParseNode, ParseToAst as parseAst, YAMLNode } from "../ref/yaml";
|
||||
import { From } from "linq-es2015";
|
||||
import { RawSourceMap, SourceMapGenerator, SourceMapConsumer } from "source-map";
|
||||
import { Compile, CompilePosition } from "../source-map/source-map";
|
||||
import { BlameTree } from "../source-map/blaming";
|
||||
import { Lazy, LazyPromise } from '../lazy';
|
||||
import { Lazy } from "../lazy";
|
||||
import { IFileSystem } from "../file-system";
|
||||
import { OperationCanceledException } from "../exception";
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export enum DocumentType {
|
||||
Markdown = <any>"markdown",
|
||||
Yaml = <any>"yaml",
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import * as events from 'events';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as events from "events";
|
||||
|
||||
export interface IEvent<TSender extends events.EventEmitter, TArgs> {
|
||||
Subscribe(fn: (sender: TSender, args: TArgs) => void): () => void;
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
export class Exception extends Error {
|
||||
constructor(message: string, public exitCode: number = 1) {
|
||||
super(message);
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import { EnumerateFiles, ExistsUri } from './ref/uri';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { EnumerateFiles } from "./ref/uri";
|
||||
import { From } from "./ref/linq";
|
||||
import * as a from "./ref/async";
|
||||
import { ResolveUri, ReadUri, WriteString } from "./ref/uri";
|
||||
import * as Constants from "./constants";
|
||||
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
import { EnhancedPosition, Position, SmartPosition } from './ref/source-map';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { EnhancedPosition, Position } from "./ref/source-map";
|
||||
|
||||
export enum Channel {
|
||||
Information = <any>"information",
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Why not observables or on "data"&"end" pattern?
|
||||
*
|
||||
* - syntax support of MultiPromise
|
||||
* - you can `await` to consume them
|
||||
* - you can use `async` methods to create them
|
||||
* - "data"&"end" pattern has drawbacks
|
||||
* - on consumer side
|
||||
* - single occurrence of "end" purely contractual and NOT guaranteed by type system! => pot. source of bugs
|
||||
* - if all data is required for processing, it has to be collected manually (introduces mutable state)
|
||||
* - on producer side
|
||||
* - event subscription system requires mutable state (list of subscribers)
|
||||
* - in general
|
||||
* - can a consumer unsubscribe? how? (sounds like further state!)
|
||||
* - can a consumer miss some events by subscribing "too late", i.e. after an event was fired?
|
||||
* - if yes: induces management complexity (all pipeline steps have to be hooked up FULLY before starting any computation)
|
||||
* - if no: so you have to buffer everything. even after "end" was fired, someone may subscribe...
|
||||
* - in contrast, MultiPromise provides all that for free
|
||||
* - immutable data structure, no explicit state
|
||||
* - type system enforces order of events and single end of things
|
||||
* - minimum amount of "past events" stored due to single linked list strucutre:
|
||||
* - whoever holds a MultiPromise prevents garbage collection
|
||||
* - consumption of an event effectively decrements ref-count on associated node
|
||||
* - leverages error infrastrucure of Promise
|
||||
* - easy to "marshal" from/to any other paradigm (events, streams, regular promises, ...)
|
||||
*/
|
||||
|
||||
|
||||
export type MultiPromiseItem<T> = { readonly current: T, readonly next: MultiPromise<T> };
|
||||
export type MultiPromise<T> = Promise<MultiPromiseItem<T> | null>;
|
||||
|
||||
export module MultiPromiseUtility {
|
||||
export function empty<T>(): MultiPromise<T> {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
export async function list<T>(items: T[]): MultiPromise<T> {
|
||||
let result: MultiPromise<T> = empty<T>();
|
||||
for (const item of items.reverse()) {
|
||||
result = Promise.resolve({
|
||||
current: item,
|
||||
next: result
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function single<T>(value: T): MultiPromise<T> {
|
||||
return fromPromise<T>(Promise.resolve(value));
|
||||
}
|
||||
export function fromPromise<T>(promise: Promise<T>): MultiPromise<T> {
|
||||
return new Promise<{ current: T, next: MultiPromise<T> }>((resolve, reject) => {
|
||||
promise.then(value => resolve({ current: value, next: empty<T>() }));
|
||||
promise.catch(err => reject(err));
|
||||
});
|
||||
}
|
||||
export async function bind<T, U>(promise: MultiPromise<T>, f: (item: T) => MultiPromise<U>): MultiPromise<U> {
|
||||
const node = await promise;
|
||||
if (node === null) {
|
||||
return null;
|
||||
}
|
||||
const sub = f(node.current);
|
||||
return concatRace(sub, bind(node.next, f));
|
||||
}
|
||||
|
||||
export function deferred<T>(promise: Promise<MultiPromise<T>>): MultiPromise<T> {
|
||||
return bind(fromPromise(promise), x => x);
|
||||
}
|
||||
|
||||
export async function toAsyncCallbacks<T>(promise: MultiPromise<T>, callback: (item: T) => Promise<void>): Promise<void> {
|
||||
let res: MultiPromiseItem<T> | null;
|
||||
while (res = await promise) {
|
||||
await callback(res.current);
|
||||
promise = res.next;
|
||||
}
|
||||
}
|
||||
|
||||
export function toCallbacks<T>(promise: MultiPromise<T>, callback: (item: T) => void): Promise<void> {
|
||||
return toAsyncCallbacks(promise, async item => callback(item));
|
||||
}
|
||||
|
||||
export function fromCallbacks<T>(executor: (callback: (item: T) => void) => Promise<void>): MultiPromise<T> {
|
||||
let nextResolve: (item: MultiPromiseItem<T> | null) => void;
|
||||
const end = () => { nextResolve(null); nextResolve = () => { }; };
|
||||
const next = () => new Promise<MultiPromiseItem<T> | null>(res => nextResolve = res);
|
||||
const result = next();
|
||||
const worker = async () => {
|
||||
await executor(item => {
|
||||
nextResolve({
|
||||
current: item,
|
||||
next: next()
|
||||
})
|
||||
});
|
||||
end();
|
||||
};
|
||||
process.nextTick(async () => {
|
||||
try {
|
||||
await worker();
|
||||
} catch (e) {
|
||||
console.error(`Error occurred in callback executor:`);
|
||||
console.error(e);
|
||||
end();
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function gather<T>(promise: MultiPromise<T>): Promise<T[]> {
|
||||
const result: T[] = [];
|
||||
await toCallbacks(promise, item => result.push(item));
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function getSingle<T>(promise: MultiPromise<T>): Promise<T> {
|
||||
const result = await gather<T>(promise);
|
||||
if (result.length !== 1) {
|
||||
throw new Error(`Expected single item but got ${result.length}`);
|
||||
}
|
||||
return result[0];
|
||||
}
|
||||
|
||||
export async function map<T, U>(promise: MultiPromise<T>, selector: (item: T, index: number) => Promise<U>, startIndex: number = 0): MultiPromise<U> {
|
||||
const head = await promise;
|
||||
if (head === null) {
|
||||
return null;
|
||||
}
|
||||
const current = await selector(head.current, startIndex);
|
||||
return {
|
||||
current: current,
|
||||
next: map(head.next, selector, startIndex + 1)
|
||||
};
|
||||
}
|
||||
|
||||
function race<T>(a: Promise<T>, b: Promise<T>): Promise<[T, Promise<T>]> {
|
||||
return Promise.race([a.then(x => [x, b]), b.then(x => [x, a])]);
|
||||
}
|
||||
|
||||
export async function concatRace<T>(a: MultiPromise<T>, b: MultiPromise<T>): MultiPromise<T> {
|
||||
const [winner, loser] = await race(a, b);
|
||||
if (winner === null) {
|
||||
return loser;
|
||||
}
|
||||
return {
|
||||
current: winner.current,
|
||||
next: concatRace(winner.next, loser)
|
||||
};
|
||||
}
|
||||
export function joinRace<T>(...promise: MultiPromise<T>[]): MultiPromise<T> {
|
||||
return promise.reduce(concatRace, MultiPromiseUtility.empty<T>());
|
||||
}
|
||||
|
||||
export async function concat<T>(a: MultiPromise<T>, b: MultiPromise<T>): MultiPromise<T> {
|
||||
const head = await a;
|
||||
if (head === null) {
|
||||
return b;
|
||||
}
|
||||
return {
|
||||
current: head.current,
|
||||
next: concat(head.next, b)
|
||||
};
|
||||
}
|
||||
export function join<T>(...promise: MultiPromise<T>[]): MultiPromise<T> {
|
||||
return promise.reduce(concat, MultiPromiseUtility.empty<T>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class MultiPromiseBuilder<T> {
|
||||
private resolve: (promise: MultiPromise<T>) => void;
|
||||
private deferredPromise: MultiPromise<T>;
|
||||
private sources: MultiPromise<T>[] | null = [];
|
||||
|
||||
public constructor() {
|
||||
this.deferredPromise = MultiPromiseUtility.deferred(new Promise(resolve => this.resolve = resolve));
|
||||
}
|
||||
|
||||
public get Promise(): MultiPromise<T> {
|
||||
return this.deferredPromise;
|
||||
}
|
||||
|
||||
public AddSource(promise: MultiPromise<T>): void {
|
||||
if (!this.sources) {
|
||||
throw new Error("Promise has already been built.");
|
||||
}
|
||||
this.sources.push(promise);
|
||||
}
|
||||
|
||||
public Build(): void {
|
||||
if (!this.sources) {
|
||||
throw new Error("Promise has already been built.");
|
||||
}
|
||||
const sources = this.sources;
|
||||
this.sources = null;
|
||||
this.resolve(MultiPromiseUtility.joinRace(...sources));
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { OutstandingTaskAlreadyCompletedException } from './exception';
|
||||
import { OutstandingTaskAlreadyCompletedException } from "./exception";
|
||||
|
||||
export class OutstandingTaskAwaiter {
|
||||
private locked: boolean = false;
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
import { OperationAbortedException } from '../exception';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Descendants, Kind, CloneAst, YAMLMapping, newScalar, ParseNode } from "../ref/yaml";
|
||||
import { MergeYamls, IdentitySourceMapping, resolveRValue } from "../source-map/merging";
|
||||
import { Mapping } from "../ref/source-map";
|
||||
import { OperationAbortedException } from "../exception";
|
||||
import { ParseNode } from "../ref/yaml";
|
||||
import { MergeYamls, resolveRValue } from "../source-map/merging";
|
||||
import { DataHandleRead, DataHandleWrite, DataStoreView } from "../data-store/data-store";
|
||||
import { Parse as ParseLiterate } from "./literate";
|
||||
import { IndexToPosition, Lines } from "./text-utility";
|
||||
import { IndexToPosition } from "./text-utility";
|
||||
import { ConfigurationView } from "../autorest-core";
|
||||
import { Channel, Message, SourceLocation, Range } from "../message";
|
||||
import { Channel, SourceLocation } from "../message";
|
||||
import { safeEval } from "../ref/safe-eval";
|
||||
|
||||
export class CodeBlock {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { DataHandleRead } from '../data-store/data-store';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { DataHandleRead } from "../data-store/data-store";
|
||||
|
||||
const regexNewLine = /\r?\n/g;
|
||||
|
||||
export function LineIndices(text: string): number[] {
|
||||
|
|
|
@ -61,7 +61,7 @@ export async function ProcessCodeModel(codeModel: DataHandleRead, scope: DataSto
|
|||
const nodeOriginal = CloneAst(node);
|
||||
const key = nodeOriginal.key.value;
|
||||
const origKey = key + "_Original";
|
||||
nodeOriginal.key.value = origKey
|
||||
nodeOriginal.key.value = origKey;
|
||||
parent.mappings.push(nodeOriginal);
|
||||
mapping.push({
|
||||
name: "original gfm",
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { nodes } from '../ref/jsonpath';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { nodes } from "../ref/jsonpath";
|
||||
import { safeEval } from "../ref/safe-eval";
|
||||
import { ManipulateObject } from "./object-manipulator";
|
||||
import { DataHandleRead, DataStoreView } from "../data-store/data-store";
|
||||
import { DirectiveView } from "../configuration";
|
||||
import { ConfigurationView } from "../autorest-core";
|
||||
import { From } from "../ref/linq";
|
||||
import { Channel, Message, SourceLocation } from '../message';
|
||||
import { Channel, Message, SourceLocation } from "../message";
|
||||
|
||||
export class Manipulator {
|
||||
private transformations: DirectiveView[];
|
||||
|
@ -80,7 +80,7 @@ export class Manipulator {
|
|||
const doc = data.ReadObject<any>();
|
||||
const allHits = nodes(doc, w);
|
||||
for (const hit of allHits) {
|
||||
let testResults = [...safeEval<any>(`(function* () { ${t.indexOf('yield') === -1 ? `yield (${t}\n)` : `${t}\n`} })()`, { $: hit.value, $doc: doc, $path: hit.path })];
|
||||
let testResults = [...safeEval<any>(`(function* () { ${t.indexOf("yield") === -1 ? `yield (${t}\n)` : `${t}\n`} })()`, { $: hit.value, $doc: doc, $path: hit.path })];
|
||||
for (const testResult of testResults) {
|
||||
if (testResult === false || typeof testResult !== "boolean") {
|
||||
const messageText = typeof testResult === "string" ? testResult : "Custom test failed";
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
import { JsonPath, stringify } from '../ref/jsonpath';
|
||||
import { safeEval } from '../ref/safe-eval';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { JsonPath, stringify } from "../ref/jsonpath";
|
||||
import { safeEval } from "../ref/safe-eval";
|
||||
import { LazyPromise } from "../lazy";
|
||||
import { OutstandingTaskAwaiter } from "../outstanding-task-awaiter";
|
||||
import { AutoRestPlugin } from "./plugin-endpoint";
|
||||
import { Manipulator } from "./manipulation";
|
||||
import { ProcessCodeModel } from "./commonmark-documentation";
|
||||
import { Channel } from "../message";
|
||||
import { MultiPromise } from "../multi-promise";
|
||||
import { ResolveUri } from "../ref/uri";
|
||||
import { ConfigurationView } from "../configuration";
|
||||
import { DataHandleRead, DataStoreView, DataStoreViewReadonly, QuickScope } from "../data-store/data-store";
|
||||
|
@ -20,9 +19,7 @@ import { ComposeSwaggers, LoadLiterateSwaggers, LoadLiterateSwaggerOverrides } f
|
|||
import { IFileSystem } from "../file-system";
|
||||
import { EmitArtifacts } from "./artifact-emitter";
|
||||
|
||||
export type DataPromise = MultiPromise<DataHandleRead>;
|
||||
|
||||
type PipelinePlugin = (config: ConfigurationView, input: DataStoreViewReadonly, working: DataStoreView, output: DataStoreView) => Promise<void>;
|
||||
export type PipelinePlugin = (config: ConfigurationView, input: DataStoreViewReadonly, working: DataStoreView, output: DataStoreView) => Promise<void>;
|
||||
interface PipelineNode {
|
||||
outputArtifact?: string;
|
||||
pluginName: string;
|
||||
|
@ -63,8 +60,9 @@ function CreatePluginTransformer(): PipelinePlugin {
|
|||
};
|
||||
const manipulator = new Manipulator(config);
|
||||
const files = await input.Enum();
|
||||
for (const file of files) {
|
||||
for (let file of files) {
|
||||
const fileIn = await input.ReadStrict(file);
|
||||
file = file.substr(file.indexOf("/output/") + "/output/".length);
|
||||
const fileOut = await manipulator.Process(fileIn, working, documentIdResolver(file));
|
||||
await (await output.Write("./" + file)).Forward(fileOut);
|
||||
}
|
||||
|
@ -78,7 +76,7 @@ function CreatePluginTransformerImmediate(): PipelinePlugin {
|
|||
};
|
||||
const files = await input.Enum(); // first all the immediate-configs, then a single swagger-document
|
||||
const scopes = await Promise.all(files.slice(0, files.length - 1).map(f => input.ReadStrict(f)));
|
||||
const manipulator = new Manipulator(config.GetPluginViewImmediate(...scopes.map(s => s.ReadObject<any>())));
|
||||
const manipulator = new Manipulator(config.GetNestedConfigurationImmediate(...scopes.map(s => s.ReadObject<any>())));
|
||||
const file = files[files.length - 1];
|
||||
const fileIn = await input.ReadStrict(file);
|
||||
const fileOut = await manipulator.Process(fileIn, working, documentIdResolver(file));
|
||||
|
@ -94,7 +92,7 @@ function CreatePluginComposer(): PipelinePlugin {
|
|||
await (await output.Write("composed")).Forward(swagger);
|
||||
};
|
||||
}
|
||||
function CreatePluginExternal(host: PromiseLike<AutoRestPlugin>, pluginName: string, fullKeys: boolean = true): PipelinePlugin {
|
||||
function CreatePluginExternal(host: PromiseLike<AutoRestPlugin>, pluginName: string): PipelinePlugin {
|
||||
return async (config, input, working, output) => {
|
||||
const plugin = await host;
|
||||
const pluginNames = await plugin.GetPluginNames(config.CancellationToken);
|
||||
|
@ -102,11 +100,6 @@ function CreatePluginExternal(host: PromiseLike<AutoRestPlugin>, pluginName: str
|
|||
throw new Error(`Plugin ${pluginName} not found.`);
|
||||
}
|
||||
|
||||
// forward input scope (relative/absolute key mess...)
|
||||
if (fullKeys) {
|
||||
input = new QuickScope(await Promise.all((await input.Enum()).map(x => input.ReadStrict(x))));
|
||||
}
|
||||
|
||||
const result = await plugin.Process(
|
||||
pluginName,
|
||||
key => config.GetEntry(key as any),
|
||||
|
@ -122,9 +115,10 @@ function CreatePluginExternal(host: PromiseLike<AutoRestPlugin>, pluginName: str
|
|||
function CreateCommonmarkProcessor(): PipelinePlugin {
|
||||
return async (config, input, working, output) => {
|
||||
const files = await input.Enum();
|
||||
for (const file of files) {
|
||||
for (let file of files) {
|
||||
const fileIn = await input.ReadStrict(file);
|
||||
const fileOut = await ProcessCodeModel(fileIn, working);
|
||||
file = file.substr(file.indexOf("/output/") + "/output/".length);
|
||||
await (await output.Write("./" + file + "/_code-model-v1")).Forward(fileOut);
|
||||
}
|
||||
};
|
||||
|
@ -250,6 +244,8 @@ export async function RunPipeline(configView: ConfigurationView, fileSystem: IFi
|
|||
|
||||
// externals:
|
||||
const oavPluginHost = new LazyPromise(async () => await AutoRestPlugin.FromModule(`${__dirname}/plugins/openapi-validation-tools`));
|
||||
const aiPluginHost = new LazyPromise(async () => await AutoRestPlugin.FromModule(`${__dirname}/../../node_modules/autorest-interactive`));
|
||||
const aoavPluginHost = new LazyPromise(async () => await AutoRestPlugin.FromModule(`${__dirname}/../../node_modules/azure-openapi-validator`));
|
||||
const autoRestDotNet = new LazyPromise(async () => await GetAutoRestDotNetPlugin());
|
||||
|
||||
// TODO: enhance with custom declared plugins
|
||||
|
@ -262,6 +258,7 @@ export async function RunPipeline(configView: ConfigurationView, fileSystem: IFi
|
|||
"model-validator": CreatePluginExternal(oavPluginHost, "model-validator"),
|
||||
"semantic-validator": CreatePluginExternal(oavPluginHost, "semantic-validator"),
|
||||
"azure-validator": CreatePluginExternal(autoRestDotNet, "azure-validator"),
|
||||
"azure-openapi-validator": CreatePluginExternal(aoavPluginHost, "azure-openapi-validator"),
|
||||
"modeler": CreatePluginExternal(autoRestDotNet, "modeler"),
|
||||
|
||||
"csharp": CreatePluginExternal(autoRestDotNet, "csharp"),
|
||||
|
@ -272,11 +269,36 @@ export async function RunPipeline(configView: ConfigurationView, fileSystem: IFi
|
|||
"java": CreatePluginExternal(autoRestDotNet, "java"),
|
||||
"azureresourceschema": CreatePluginExternal(autoRestDotNet, "azureresourceschema"),
|
||||
"jsonrpcclient": CreatePluginExternal(autoRestDotNet, "jsonrpcclient"),
|
||||
"csharp-simplifier": CreatePluginExternal(autoRestDotNet, "csharp-simplifier", false),
|
||||
"csharp-simplifier": CreatePluginExternal(autoRestDotNet, "csharp-simplifier"),
|
||||
|
||||
"commonmarker": CreateCommonmarkProcessor(),
|
||||
"emitter": CreateArtifactEmitter(),
|
||||
"pipeline-emitter": CreateArtifactEmitter(async () => new QuickScope([await (await configView.DataStore.Write("pipeline")).WriteObject(pipeline.pipeline)]))
|
||||
"pipeline-emitter": CreateArtifactEmitter(async () => new QuickScope([await (await configView.DataStore.Write("pipeline")).WriteObject(pipeline.pipeline)])),
|
||||
"autorest-interactive": async (
|
||||
config: ConfigurationView,
|
||||
input: DataStoreViewReadonly,
|
||||
working: DataStoreView,
|
||||
output: DataStoreView) => {
|
||||
await CreatePluginExternal(aiPluginHost, "autorest-interactive")(
|
||||
config.GetNestedConfigurationImmediate({
|
||||
__status: new Proxy<any>({}, {
|
||||
get(_, key) {
|
||||
const expr = new Buffer(key.toString(), "base64").toString("ascii");
|
||||
try {
|
||||
return safeEval(expr, {
|
||||
pipeline: pipeline.pipeline,
|
||||
tasks: tasks
|
||||
});
|
||||
} catch (e) {
|
||||
return "" + e;
|
||||
}
|
||||
}
|
||||
})
|
||||
}),
|
||||
config.DataStore,
|
||||
working,
|
||||
output);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: think about adding "number of files in scope" kind of validation in between pipeline steps
|
||||
|
@ -293,8 +315,7 @@ export async function RunPipeline(configView: ConfigurationView, fileSystem: IFi
|
|||
let inputScopes: DataStoreViewReadonly[] = await Promise.all(node.inputs.map(getTask));
|
||||
if (inputScopes.length === 0) {
|
||||
inputScopes = [fsInput];
|
||||
}
|
||||
if (inputScopes.length > 1) {
|
||||
} else {
|
||||
const handles: DataHandleRead[] = [];
|
||||
for (const pscope of inputScopes) {
|
||||
const scope = await pscope;
|
||||
|
@ -341,7 +362,12 @@ export async function RunPipeline(configView: ConfigurationView, fileSystem: IFi
|
|||
// execute pipeline
|
||||
const barrier = new OutstandingTaskAwaiter();
|
||||
for (const name of Object.keys(pipeline.pipeline)) {
|
||||
barrier.Await(getTask(name));
|
||||
const task = getTask(name);
|
||||
const taskx: { _state: "running" | "failed" | "complete" } = task as any;
|
||||
taskx._state = "running";
|
||||
task.catch(() => taskx._state = "failed");
|
||||
task.then(() => taskx._state = "complete");
|
||||
barrier.Await(task);
|
||||
}
|
||||
await barrier.Wait();
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { RequestType0, RequestType1, RequestType2 } from "../ref/jsonrpc";
|
||||
import { NotificationType0, NotificationType1, NotificationType2, NotificationType3, NotificationType4 } from "../ref/jsonrpc";
|
||||
import { NotificationType4 } from "../ref/jsonrpc";
|
||||
import { Mapping, RawSourceMap, SmartPosition } from "../ref/source-map";
|
||||
import { Message } from "../message";
|
||||
|
||||
|
|
|
@ -1,18 +1,17 @@
|
|||
import { LazyPromise } from '../lazy';
|
||||
import { EventEmitter, IEvent } from '../events';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { MultiPromise, MultiPromiseUtility } from '../multi-promise';
|
||||
import { LazyPromise } from "../lazy";
|
||||
import { EventEmitter } from "../events";
|
||||
import { fork, ChildProcess } from "child_process";
|
||||
import { Mappings, Mapping, RawSourceMap, SmartPosition, Position } from "../ref/source-map";
|
||||
import { Mappings, RawSourceMap, SmartPosition } from "../ref/source-map";
|
||||
import { CancellationToken } from "../ref/cancallation";
|
||||
import { createMessageConnection, MessageConnection } from "../ref/jsonrpc";
|
||||
import { DataStoreViewReadonly, DataStoreView, DataHandleRead } from "../data-store/data-store";
|
||||
import { DataStoreViewReadonly, DataStoreView } from "../data-store/data-store";
|
||||
import { IAutoRestPluginInitiator_Types, IAutoRestPluginTarget_Types, IAutoRestPluginInitiator } from "./plugin-api";
|
||||
import { Channel, Message } from "../message";
|
||||
import { Message } from "../message";
|
||||
|
||||
interface IAutoRestPluginTargetEndpoint {
|
||||
GetPluginNames(cancellationToken: CancellationToken): Promise<string[]>;
|
||||
|
@ -48,7 +47,6 @@ export class AutoRestPlugin extends EventEmitter {
|
|||
);
|
||||
childProc.stderr.pipe(process.stderr);
|
||||
const plugin = new AutoRestPlugin(channel);
|
||||
channel.onClose(() => { throw "AutoRest plugin terminated."; });
|
||||
channel.listen();
|
||||
return plugin;
|
||||
}
|
||||
|
@ -83,13 +81,15 @@ export class AutoRestPlugin extends EventEmitter {
|
|||
channel.onNotification(IAutoRestPluginInitiator_Types.WriteFile, this.apiInitiator.WriteFile);
|
||||
channel.onNotification(IAutoRestPluginInitiator_Types.Message, this.apiInitiator.Message);
|
||||
|
||||
const terminationPromise = new Promise<never>((_, rej) => channel.onClose(() => { rej(new Error("AutoRest plugin terminated.")); }));
|
||||
|
||||
// target
|
||||
this.apiTarget = {
|
||||
async GetPluginNames(cancellationToken: CancellationToken): Promise<string[]> {
|
||||
return await channel.sendRequest(IAutoRestPluginTarget_Types.GetPluginNames, cancellationToken);
|
||||
return await Promise.race([terminationPromise, channel.sendRequest(IAutoRestPluginTarget_Types.GetPluginNames, cancellationToken)]);
|
||||
},
|
||||
async Process(pluginName: string, sessionId: string, cancellationToken: CancellationToken): Promise<boolean> {
|
||||
return await channel.sendRequest(IAutoRestPluginTarget_Types.Process, pluginName, sessionId, cancellationToken);
|
||||
return await Promise.race([terminationPromise, channel.sendRequest(IAutoRestPluginTarget_Types.Process, pluginName, sessionId, cancellationToken)]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -121,8 +121,6 @@ export class AutoRestPlugin extends EventEmitter {
|
|||
}
|
||||
|
||||
private static CreateEndpointFor(pluginName: string, configuration: (key: string) => any, inputScope: DataStoreViewReadonly, outputScope: DataStoreView, onMessage: (message: Message) => void, cancellationToken: CancellationToken): IAutoRestPluginInitiatorEndpoint {
|
||||
let messageId: number = 0;
|
||||
|
||||
const inputFileNames = new LazyPromise(async () => inputScope.Enum());
|
||||
const inputFileHandles = new LazyPromise(async () => {
|
||||
const names = await inputFileNames;
|
||||
|
@ -162,7 +160,7 @@ export class AutoRestPlugin extends EventEmitter {
|
|||
await finishPrev;
|
||||
notify();
|
||||
},
|
||||
async Message(message: Message, path?: SmartPosition, sourceFile?: string): Promise<void> {
|
||||
async Message(message: Message): Promise<void> {
|
||||
const finishPrev = finishNotifications;
|
||||
let notify: () => void = () => { };
|
||||
finishNotifications = new Promise<void>(res => notify = res);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { LazyPromise } from '../../lazy';
|
||||
import { LazyPromise } from "../../lazy";
|
||||
import { SpawnJsonRpcAutoRest } from "../../../interop/autorest-dotnet";
|
||||
import { AutoRestPlugin } from "../plugin-endpoint";
|
||||
|
||||
|
|
|
@ -51,5 +51,5 @@ export class Suppressor {
|
|||
return m;
|
||||
}
|
||||
|
||||
// TODO: make method that'll complain about supressions that weren't used!
|
||||
// TODO: make method that'll complain about suppressions that weren't used!
|
||||
}
|
|
@ -1,23 +1,23 @@
|
|||
import { Lines } from '../parsing/text-utility';
|
||||
import {
|
||||
CommonmarkHeadingFollowingText,
|
||||
CommonmarkHeadingText,
|
||||
CommonmarkSubHeadings,
|
||||
ParseCommonmark
|
||||
} from '../parsing/literate';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Channel, SourceLocation } from '../message';
|
||||
import { Lines } from "../parsing/text-utility";
|
||||
import {
|
||||
CommonmarkHeadingFollowingText,
|
||||
CommonmarkHeadingText,
|
||||
CommonmarkSubHeadings,
|
||||
ParseCommonmark
|
||||
} from "../parsing/literate";
|
||||
import { Channel, SourceLocation } from "../message";
|
||||
import { OperationAbortedException } from "../exception";
|
||||
import { safeEval } from "../ref/safe-eval";
|
||||
import { ConfigurationView } from "../autorest-core";
|
||||
import { DataStoreView, DataHandleRead, DataStoreViewReadonly } from "../data-store/data-store";
|
||||
import { IsPrefix, JsonPath, JsonPathComponent, stringify } from "../ref/jsonpath";
|
||||
import { ResolvePath, ResolveRelativeNode } from "../parsing/yaml";
|
||||
import { Clone, CloneAst, Descendants, StringifyAst, ToAst, YAMLNodeWithPath } from '../ref/yaml';
|
||||
import { Clone, CloneAst, Descendants, StringifyAst, ToAst, YAMLNodeWithPath } from "../ref/yaml";
|
||||
import { ResolveUri } from "../ref/uri";
|
||||
import { From } from "../ref/linq";
|
||||
import { Mappings, Mapping } from "../ref/source-map";
|
||||
|
@ -244,7 +244,7 @@ export async function LoadLiterateSwaggerOverride(config: ConfigurationView, inp
|
|||
|
||||
// replace queries
|
||||
const candidProperties = ["name", "operationId", "$ref"];
|
||||
clue = clue.replace(/\.\#(.+?)\b/g, (_, match) => `..[?(${candidProperties.map(p => `(@[${JSON.stringify(p)}] && @[${JSON.stringify(p)}].indexOf(${JSON.stringify(match)}) !== -1)`).join(' || ')})]`);
|
||||
clue = clue.replace(/\.\#(.+?)\b/g, (_, match) => `..[?(${candidProperties.map(p => `(@[${JSON.stringify(p)}] && @[${JSON.stringify(p)}].indexOf(${JSON.stringify(match)}) !== -1)`).join(" || ")})]`);
|
||||
|
||||
// console.log(clue);
|
||||
|
||||
|
@ -277,7 +277,6 @@ export async function LoadLiterateSwagger(config: ConfigurationView, inputScope:
|
|||
const data = await ParseLiterateYaml(config, await inputScope.ReadStrict(inputFileUri), workingScope.CreateScope("yaml"));
|
||||
const externalFiles: { [uri: string]: DataHandleRead } = {};
|
||||
externalFiles[inputFileUri] = data;
|
||||
//WriteString(`file:///C:/output/${(<any>workingScope).name}_before.yaml`, await externalFiles[inputFileUri].ReadData());
|
||||
await EnsureCompleteDefinitionIsPresent(config,
|
||||
inputScope,
|
||||
workingScope.CreateScope("ref-resolving"),
|
||||
|
@ -287,7 +286,6 @@ export async function LoadLiterateSwagger(config: ConfigurationView, inputScope:
|
|||
data.ReadObject<any>(),
|
||||
IdentitySourceMapping(data.key, data.ReadYamlAst()));
|
||||
const result = await StripExternalReferences(externalFiles[inputFileUri], workingScope.CreateScope("strip-ext-references"));
|
||||
//WriteString(`file:///C:/output/${(<any>workingScope).name}_after.yaml`, await result.ReadData());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import * as promisify from "pify";
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { safeEval } from './safe-eval';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { safeEval } from "./safe-eval";
|
||||
import * as jsonpath from "jsonpath";
|
||||
|
||||
// patch in smart filter expressions
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { Enumerable as IEnumerable } from "linq-es2015";
|
||||
|
||||
export { Enumerable, Enumerable as IEnumerable, From } from "linq-es2015";
|
||||
|
||||
export async function ToArray<T>(iterable: AsyncIterable<T>): Promise<Array<T>> {
|
||||
|
@ -17,13 +17,12 @@ export function Push<T>(destination: Array<T>, source: any) {
|
|||
if (source) {
|
||||
if (IsIterable(source)) {
|
||||
destination.push(...source);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
destination.push(source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function IsIterable(target: any) {
|
||||
return target && target[Symbol.iterator] && typeof target !== 'string'
|
||||
return target && target[Symbol.iterator] && typeof target !== "string";
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
import { Range } from '../message';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import { IndexToPosition } from '../parsing/text-utility';
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
@ -6,7 +5,6 @@ import { IndexToPosition } from '../parsing/text-utility';
|
|||
|
||||
import * as yamlAst from "yaml-ast-parser";
|
||||
import { JsonPath } from "./jsonpath";
|
||||
import { Message, SourceLocation, Channel } from '../message';
|
||||
import { NewEmptyObject } from "../parsing/stable-object";
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,14 +2,13 @@
|
|||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
import { OutstandingTaskAwaiter } from "../outstanding-task-awaiter";
|
||||
|
||||
import { IndexToPosition } from "../parsing/text-utility";
|
||||
import { ConfigurationView, MessageEmitter } from "../configuration";
|
||||
import { Message, Channel } from "../message";
|
||||
import { From } from "../ref/linq";
|
||||
import { ConfigurationView } from "../configuration";
|
||||
import { Channel } from "../message";
|
||||
import { JsonPath, stringify } from "../ref/jsonpath";
|
||||
import * as yaml from "../ref/yaml";
|
||||
import { Mapping, Mappings } from "../ref/source-map";
|
||||
import { Mappings } from "../ref/source-map";
|
||||
import { DataHandleRead, DataHandleWrite } from "../data-store/data-store";
|
||||
|
||||
// // TODO: may want ASTy merge! (supporting circular structure and such?)
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { EnhancedPosition, Mappings, Position, SmartPosition } from '../ref/source-map';
|
||||
import { EnhancedPosition, Mappings, SmartPosition } from "../ref/source-map";
|
||||
import { Descendants, ToAst } from "../ref/yaml";
|
||||
import { JsonPath, parse, stringify } from '../ref/jsonpath';
|
||||
import { JsonPath, stringify } from "../ref/jsonpath";
|
||||
import * as yaml from "../parsing/yaml";
|
||||
import { DataHandleRead } from "../data-store/data-store";
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
"jsonpath": "^0.2.11",
|
||||
"linq-es2015": "^2.4.13",
|
||||
"oav": "0.4.1",
|
||||
"azure-openapi-validator": "git+https://github.com/olydis/azure-openapi-validator.git#b45423f4560585e64f574bbffbb5cdf894cfbd53",
|
||||
"pify": "^2.3.0",
|
||||
"safe-eval": "^0.3.0",
|
||||
"source-map": "^0.5.6",
|
||||
|
|
|
@ -27,6 +27,14 @@ plugins:
|
|||
pipeline:
|
||||
pipeline-emitter: # emits the pipeline graph
|
||||
scope: scope-pipeline-emitter
|
||||
autorest-interactive:
|
||||
scope: autorest-interactive
|
||||
|
||||
scope-pipeline-emitter:
|
||||
input-artifact: pipeline
|
||||
is-object: true
|
||||
output-uri-expr: |
|
||||
"pipeline"
|
||||
```
|
||||
|
||||
#### Loading
|
||||
|
@ -64,11 +72,6 @@ pipeline:
|
|||
input: transform
|
||||
scope: scope-swagger-document/emitter
|
||||
|
||||
scope-pipeline-emitter:
|
||||
input-artifact: pipeline
|
||||
is-object: true
|
||||
output-uri-expr: |
|
||||
"pipeline"
|
||||
scope-swagger-document/emitter:
|
||||
input-artifact: swagger-document
|
||||
is-object: true
|
||||
|
@ -100,12 +103,22 @@ pipeline:
|
|||
|
||||
``` yaml
|
||||
pipeline:
|
||||
# validator written in C#
|
||||
swagger-document/azure-validator:
|
||||
input: transform
|
||||
scope: azure-validator-composed
|
||||
swagger-document/individual/azure-validator:
|
||||
input: individual/transform
|
||||
scope: azure-validator-individual
|
||||
# validator written in TypeScript
|
||||
swagger-document/azure-openapi-validator:
|
||||
input:
|
||||
- transform
|
||||
- azure-validator # artificial predecessor in order to ensure order of messages for CI purposes
|
||||
swagger-document/individual/azure-openapi-validator:
|
||||
input:
|
||||
- transform
|
||||
- azure-validator # artificial predecessor in order to ensure order of messages for CI purposes
|
||||
```
|
||||
|
||||
Activate `azure-validator` when setting `azure-arm`!?
|
||||
|
|
|
@ -15,7 +15,7 @@ import { parse } from "../lib/ref/jsonpath";
|
|||
|
||||
@suite class Blaming {
|
||||
|
||||
@test @timeout(30000) async "end to end blaming with literate swagger"() {
|
||||
@test @timeout(0) async "end to end blaming with literate swagger"() {
|
||||
const autoRest = new AutoRest(new RealFileSystem(), ResolveUri(CreateFolderUri(__dirname), "resources/literate-example/readme-composite.md"));
|
||||
// PumpMessagesToConsole(autoRest);
|
||||
const view = await autoRest.view;
|
||||
|
|
|
@ -89,7 +89,7 @@ import { Message, Channel } from "../lib/message";
|
|||
await pickyRun({ suppress: ["AvoidNestedProperties"], where: "$..properties.properties", from: "swagger.md" });
|
||||
}
|
||||
|
||||
@test @timeout(60000) async "set descriptions on different levels"() {
|
||||
@test @timeout(0) async "set descriptions on different levels"() {
|
||||
const autoRest = new AutoRest(new RealFileSystem(), ResolveUri(CreateFolderUri(__dirname), "resources/literate-example/"));
|
||||
|
||||
const GenerateCodeModel = async (config: any) => {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"sourceMap": true,
|
||||
"strictNullChecks": true,
|
||||
"strict": true,
|
||||
"declaration": true,
|
||||
"stripInternal": true,
|
||||
"noEmitHelpers": true,
|
||||
|
|
|
@ -123,8 +123,18 @@ class App {
|
|||
// Remove bootstrapper args from cmdline
|
||||
process.argv = From<string>(process.argv).Where(each => !RemoveArgs.Any(i => each === i || each.startsWith(`${i}=`) || each.startsWith(`${i}:`))).ToArray();
|
||||
|
||||
// use this to make the core aware that this run may be legal even without any inputs
|
||||
// this is a valid scenario for "preparation calls" to autorest like `autorest --reset` or `autorest --latest`
|
||||
const allowNoInput = () => {
|
||||
// if there is *any* other argument left, that's an indicator that the core is supposed to do something
|
||||
if (process.argv.length <= 2 /*expecting node and this script*/) {
|
||||
process.argv.push("--allow-no-input");
|
||||
}
|
||||
};
|
||||
|
||||
if (this.reset) {
|
||||
rm('-rf', Installer.RootFolder);
|
||||
allowNoInput();
|
||||
}
|
||||
|
||||
// check if we're up to date with the bootstrapper
|
||||
|
@ -176,6 +186,9 @@ class App {
|
|||
// or, grab the latest version
|
||||
this.version = 'latest';
|
||||
}
|
||||
} else {
|
||||
// a version was explicitly asked for => may just be a preparation call
|
||||
allowNoInput();
|
||||
}
|
||||
|
||||
// if necessary, go get the package we need.
|
||||
|
@ -184,7 +197,7 @@ class App {
|
|||
// find out the latest version
|
||||
let releases = await this.GetReleases();
|
||||
|
||||
if (this.version == 'latest-release') {
|
||||
if (this.version === 'latest-release') {
|
||||
Console.Verbose('Requested "latest-release" version');
|
||||
releases = releases.Where(each => each.prerelease == false);
|
||||
} else {
|
||||
|
|
|
@ -66,7 +66,7 @@ public class AzureValidator : NewPlugin
|
|||
}
|
||||
}
|
||||
}
|
||||
}, new object[0]);
|
||||
});
|
||||
}
|
||||
|
||||
protected override async Task<bool> ProcessInternal()
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Perks.JsonRPC;
|
||||
using AutoRest.Core.Extensibility;
|
||||
using AutoRest.Core;
|
||||
using AutoRest.Core.Utilities;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
public class CSharpSimplifier : NewPlugin
|
||||
{
|
||||
private string codeGenerator;
|
||||
static readonly Regex ExpectedUriPrefix = new Regex("^mem:///csharp/generate/([0-9]+/)?output/");
|
||||
|
||||
public CSharpSimplifier(Connection connection, string sessionId) : base(connection, sessionId)
|
||||
{ }
|
||||
|
@ -23,7 +22,11 @@ public class CSharpSimplifier : NewPlugin
|
|||
var files = await ListInputs();
|
||||
foreach (var file in files)
|
||||
{
|
||||
fs.WriteAllText(file, await ReadFile(file));
|
||||
if (!ExpectedUriPrefix.IsMatch(file))
|
||||
{
|
||||
throw new FormatException($"Unexpected file URI format: '{file}'");
|
||||
}
|
||||
fs.WriteAllText(ExpectedUriPrefix.Replace(file, ""), await ReadFile(file));
|
||||
}
|
||||
|
||||
// simplify
|
||||
|
|
|
@ -46,7 +46,7 @@ public abstract class NewPlugin
|
|||
public Task<string> GetValue(string key) => GetValue<string>(key);
|
||||
public Task<string[]> ListInputs() => _connection.Request<string[]>("ListInputs", _sessionId);
|
||||
|
||||
public void Message(Message message, object sourcemap) => _connection.Notify("Message", _sessionId, message, sourcemap);
|
||||
public void Message(Message message) => _connection.Notify("Message", _sessionId, message);
|
||||
public void WriteFile(string filename, string content, object sourcemap) => _connection.Notify("WriteFile", _sessionId, filename, content, sourcemap);
|
||||
|
||||
protected string _sessionId;
|
||||
|
@ -73,7 +73,7 @@ public abstract class NewPlugin
|
|||
{
|
||||
Channel = "fatal",
|
||||
Text = e.ToString()
|
||||
}, null);
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -638,7 +638,8 @@ task 'regenerate-samples', '', (done) ->
|
|||
.filter((file) -> file.match(/.(map|txt)$/))
|
||||
.forEach((file) ->
|
||||
sed "-i", /\bfile:\/\/[^\s]*\/autorest[^\/\\]*/g, "", file # blame locations
|
||||
sed "-i", /\sat .*/g, "at ...", file # exception stack traces
|
||||
sed "-i", /\sat .*/g, "at ...", file # exception stack traces
|
||||
(cat file).replace(/(at \.\.\.\s*)+/g, "at ...\n").to(file) # minify exception stack traces
|
||||
)
|
||||
next null
|
||||
, true # don't fail on failures (since we wanna record them)
|
||||
|
|
|
@ -8,9 +8,9 @@ namespace AutoRest.Swagger.Validation.Core
|
|||
[Flags]
|
||||
public enum ValidationCategory
|
||||
{
|
||||
None = 1 << 0,
|
||||
RPCViolation = 1 << 1,
|
||||
OneAPIViolation = 1 << 2,
|
||||
SDKViolation = 1 << 3
|
||||
None = 0,
|
||||
RPCViolation = 1 << 0,
|
||||
OneAPIViolation = 1 << 1,
|
||||
SDKViolation = 1 << 2
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче