Skip to content

Commit

Permalink
Support enum (#643)
Browse files Browse the repository at this point in the history
* support enum

* fix diff from m3

* llcsharp-v2 should rely on modifiers-v2

Co-authored-by: xichen <xichen@microsoft.com>
Co-authored-by: Xiaogang <xidi@microsoft.com>
  • Loading branch information
3 people authored Jul 29, 2020
1 parent b1f482c commit 67674b2
Show file tree
Hide file tree
Showing 16 changed files with 1,082 additions and 171 deletions.
7 changes: 5 additions & 2 deletions powershell/autorest-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,14 @@ pipeline:
psnamer-v2:
input: csnamer-v2

add-azure-completers-v2:
modifiers-v2:
input: psnamer-v2

add-azure-completers-v2:
input: modifiers-v2

llcsharp-v2:
input: add-azure-completers-v2
input: modifiers-v2

powershell-v2:
input: add-azure-completers-v2
Expand Down
2 changes: 1 addition & 1 deletion powershell/cmdlets/class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2580,7 +2580,7 @@ export class NewCmdletClass extends Class {
regularCmdletParameter.add(new Attribute(AllowEmptyCollectionAttribute));
}

NewAddInfoAttribute(regularCmdletParameter, propertyType, vParam.required ?? false, false, vParam.description, origin.details.default.serializedName);
NewAddInfoAttribute(regularCmdletParameter, propertyType, vParam.required ?? false, false, vParam.description, origin.name);
NewAddCompleterInfo(regularCmdletParameter, vParam);
addDefaultInfo(regularCmdletParameter, vParam);

Expand Down
202 changes: 103 additions & 99 deletions powershell/enums/namespace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { IArgumentCompleter, CompletionResult, CommandAst, CompletionResultType,
import { join } from 'path';
import { DeepPartial } from '@azure-tools/codegen';

import { EnumDetails as NewEnumDetails } from '../utils/schema';

export class EnumNamespace extends Namespace {
public get outputFolder(): string {
return join(this.state.project.apiFolder, 'Support');
Expand Down Expand Up @@ -127,104 +129,106 @@ export class NewEnumNamespace extends Namespace {
constructor(parent: Namespace, public state: NewState, objectInitializer?: DeepPartial<EnumNamespace>) {
super('Support', parent);
this.apply(objectInitializer);
// skip-for-time-being
// const enumInfos = values(state.model.schemas)
// .where(each => each.details.csharp.enum !== undefined && !each.details.csharp.skip)
// .select(each => ({ details: <EnumDetails>each.details.csharp.enum, description: each.details.csharp.description }))
// .toArray();

// const done = new Set<string>();


// for (const enumInfo of enumInfos) {
// if (done.has(enumInfo.details.name)) {
// continue;
// }

// done.add(enumInfo.details.name);

// if (state.project.azure && /^api-?version$/i.exec(enumInfo.details.name)) {
// continue;
// }

// // generate a typeconverter for the enum class too.

// const enumValues = values(enumInfo.details.values).select(v => <string>v.value).toArray();
// const enumClass = new Struct(this, enumInfo.details.name, undefined, {
// interfaces: [IArgumentCompleter],
// partial: true,
// description: enumInfo.description || `Argument completer implementation for ${enumInfo.details.name}.`,
// fileName: `${enumInfo.details.name}.Completer`
// });
// const commandName = new Parameter('commandName', System.String, { description: 'The name of the command that needs argument completion.' });
// const parameterName = new Parameter('parameterName', System.String, { description: 'The name of the parameter that needs argument completion.' });
// const wordToComplete = new Parameter('wordToComplete', System.String, { description: 'The (possibly empty) word being completed.' });
// const commandAst = new Parameter('commandAst', CommandAst, { description: 'The command ast in case it is needed for completion.' });
// const fakeBoundParameters = new Parameter('fakeBoundParameters', System.Collections.IDictionary, { description: 'This parameter is similar to $PSBoundParameters, except that sometimes PowerShell cannot or will not attempt to evaluate an argument, in which case you may need to use commandAst.' });
// const completeArgumentParams = [commandName, parameterName, wordToComplete, commandAst, fakeBoundParameters];

// enumClass.add(new Method('CompleteArgument', System.Collections.Generic.IEnumerable(CompletionResult), { parameters: completeArgumentParams, description: 'Implementations of this function are called by PowerShell to complete arguments.', returnsDescription: 'A collection of completion results, most like with ResultType set to ParameterValue.' })).add(function* () {
// for (const enumValue of enumValues) {
// yield If(`${System.String.declaration}.IsNullOrEmpty(${wordToComplete.name}) || "${enumValue}".StartsWith(${wordToComplete.name}, ${System.StringComparison.declaration}.InvariantCultureIgnoreCase)`,
// `yield return new ${CompletionResult.declaration}("${enumValue}", "${enumValue}", ${CompletionResultType.declaration}.ParameterValue, "${enumValue}");`);
// }
// });


// // generate a typeconverter for the enum class too.

// const converterClass = new Class(this, `${enumInfo.details.name}TypeConverter`, undefined, {
// interfaces: [PSTypeConverter],
// partial: true,
// description: enumInfo.description || `TypeConverter implementation for ${enumInfo.details.name}.`,
// fileName: `${enumInfo.details.name}.TypeConverter`
// });

// converterClass.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, dotnet.True, {
// override: Modifier.Override,
// parameters: [
// new Parameter('sourceValue', dotnet.Object, { description: 'the <see cref="System.Object"/> to convert from' }),
// new Parameter('destinationType', System.Type, { description: 'the <see cref="System.Type" /> to convert to' })
// ],
// description: 'Determines if the converter can convert the <see cref="sourceValue"/> parameter to the <see cref="destinationType" /> parameter.',
// returnsDescription: '<c>true</c> if the converter can convert the <see cref="sourceValue"/> parameter to the <see cref="destinationType" /> parameter, otherwise <c>false</c>.',
// }));

// converterClass.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, {
// override: Modifier.Override,
// parameters: [
// new Parameter('sourceValue', dotnet.Object, { description: 'the <see cref="System.Object"/> to convert from' }),
// new Parameter('destinationType', System.Type, { description: 'the <see cref="System.Type" /> to convert to' })
// ],
// description: 'Determines if the converter can convert the <see cref="sourceValue"/> parameter to the <see cref="destinationType" /> parameter.',
// returnsDescription: '<c>true</c> if the converter can convert the <see cref="sourceValue"/> parameter to the <see cref="destinationType" /> parameter, otherwise <c>false</c>.',
// }));

// converterClass.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression(`${enumInfo.details.name}.CreateFrom(sourceValue)`), {
// override: Modifier.Override,
// parameters: [
// new Parameter('sourceValue', dotnet.Object, { description: 'the <see cref="System.Object"/> to convert from' }),
// new Parameter('destinationType', System.Type, { description: 'the <see cref="System.Type" /> to convert to' }),
// new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }),
// new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to <c>true</c>, will ignore the case when converting.' }),
// ],
// description: 'Converts the <see cref="sourceValue" /> parameter to the <see cref="destinationType" /> parameter using <see cref="formatProvider" /> and <see cref="ignoreCase" /> ',
// returnsDescription: `an instance of <see cref="${enumInfo.details.name}" />, or <c>null</c> if there is no suitable conversion.`
// }));

// converterClass.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, {
// override: Modifier.Override,
// parameters: [
// new Parameter('sourceValue', dotnet.Object, { description: 'the <see cref="System.Object"/> to convert from' }),
// new Parameter('destinationType', System.Type, { description: 'the <see cref="System.Type" /> to convert to' }),
// new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }),
// new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to <c>true</c>, will ignore the case when converting.' }),
// ], description: 'NotImplemented -- this will return <c>null</c>',
// returnsDescription: 'will always return <c>null</c>.'
// }));

// enumClass.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] }));

// }
const enumInfos = [...state.model.schemas.sealedChoices ?? [], ...state.model.schemas.choices ?? []]
.filter((choice) => !choice.language.csharp?.skip)
.map((choice) => {
return {
details: <NewEnumDetails>choice.language.csharp?.enum,
description: choice.language.csharp?.description
}
});

const done = new Set<string>();

for (const enumInfo of enumInfos) {
if (done.has(enumInfo.details.name)) {
continue;
}

done.add(enumInfo.details.name);

if (state.project.azure && /^api-?version$/i.exec(enumInfo.details.name)) {
continue;
}

// generate a typeconverter for the enum class too.

const enumValues = values(enumInfo.details.values).select(v => <string>v.value).toArray();
const enumClass = new Struct(this, enumInfo.details.name, undefined, {
interfaces: [IArgumentCompleter],
partial: true,
description: enumInfo.description || `Argument completer implementation for ${enumInfo.details.name}.`,
fileName: `${enumInfo.details.name}.Completer`
});
const commandName = new Parameter('commandName', System.String, { description: 'The name of the command that needs argument completion.' });
const parameterName = new Parameter('parameterName', System.String, { description: 'The name of the parameter that needs argument completion.' });
const wordToComplete = new Parameter('wordToComplete', System.String, { description: 'The (possibly empty) word being completed.' });
const commandAst = new Parameter('commandAst', CommandAst, { description: 'The command ast in case it is needed for completion.' });
const fakeBoundParameters = new Parameter('fakeBoundParameters', System.Collections.IDictionary, { description: 'This parameter is similar to $PSBoundParameters, except that sometimes PowerShell cannot or will not attempt to evaluate an argument, in which case you may need to use commandAst.' });
const completeArgumentParams = [commandName, parameterName, wordToComplete, commandAst, fakeBoundParameters];

enumClass.add(new Method('CompleteArgument', System.Collections.Generic.IEnumerable(CompletionResult), { parameters: completeArgumentParams, description: 'Implementations of this function are called by PowerShell to complete arguments.', returnsDescription: 'A collection of completion results, most like with ResultType set to ParameterValue.' })).add(function* () {
for (const enumValue of enumValues) {
yield If(`${System.String.declaration}.IsNullOrEmpty(${wordToComplete.name}) || "${enumValue}".StartsWith(${wordToComplete.name}, ${System.StringComparison.declaration}.InvariantCultureIgnoreCase)`,
`yield return new ${CompletionResult.declaration}("${enumValue}", "${enumValue}", ${CompletionResultType.declaration}.ParameterValue, "${enumValue}");`);
}
});


// generate a typeconverter for the enum class too.

const converterClass = new Class(this, `${enumInfo.details.name}TypeConverter`, undefined, {
interfaces: [PSTypeConverter],
partial: true,
description: enumInfo.description || `TypeConverter implementation for ${enumInfo.details.name}.`,
fileName: `${enumInfo.details.name}.TypeConverter`
});

converterClass.add(new LambdaMethod('CanConvertFrom', dotnet.Bool, dotnet.True, {
override: Modifier.Override,
parameters: [
new Parameter('sourceValue', dotnet.Object, { description: 'the <see cref="System.Object"/> to convert from' }),
new Parameter('destinationType', System.Type, { description: 'the <see cref="System.Type" /> to convert to' })
],
description: 'Determines if the converter can convert the <see cref="sourceValue"/> parameter to the <see cref="destinationType" /> parameter.',
returnsDescription: '<c>true</c> if the converter can convert the <see cref="sourceValue"/> parameter to the <see cref="destinationType" /> parameter, otherwise <c>false</c>.',
}));

converterClass.add(new LambdaMethod('CanConvertTo', dotnet.Bool, dotnet.False, {
override: Modifier.Override,
parameters: [
new Parameter('sourceValue', dotnet.Object, { description: 'the <see cref="System.Object"/> to convert from' }),
new Parameter('destinationType', System.Type, { description: 'the <see cref="System.Type" /> to convert to' })
],
description: 'Determines if the converter can convert the <see cref="sourceValue"/> parameter to the <see cref="destinationType" /> parameter.',
returnsDescription: '<c>true</c> if the converter can convert the <see cref="sourceValue"/> parameter to the <see cref="destinationType" /> parameter, otherwise <c>false</c>.',
}));

converterClass.add(new LambdaMethod('ConvertFrom', dotnet.Object, new LiteralExpression(`${enumInfo.details.name}.CreateFrom(sourceValue)`), {
override: Modifier.Override,
parameters: [
new Parameter('sourceValue', dotnet.Object, { description: 'the <see cref="System.Object"/> to convert from' }),
new Parameter('destinationType', System.Type, { description: 'the <see cref="System.Type" /> to convert to' }),
new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }),
new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to <c>true</c>, will ignore the case when converting.' }),
],
description: 'Converts the <see cref="sourceValue" /> parameter to the <see cref="destinationType" /> parameter using <see cref="formatProvider" /> and <see cref="ignoreCase" /> ',
returnsDescription: `an instance of <see cref="${enumInfo.details.name}" />, or <c>null</c> if there is no suitable conversion.`
}));

converterClass.add(new LambdaMethod('ConvertTo', dotnet.Object, dotnet.Null, {
override: Modifier.Override,
parameters: [
new Parameter('sourceValue', dotnet.Object, { description: 'the <see cref="System.Object"/> to convert from' }),
new Parameter('destinationType', System.Type, { description: 'the <see cref="System.Type" /> to convert to' }),
new Parameter('formatProvider', System.IFormatProvider, { description: 'not used by this TypeConverter.' }),
new Parameter('ignoreCase', dotnet.Bool, { description: 'when set to <c>true</c>, will ignore the case when converting.' }),
], description: 'NotImplemented -- this will return <c>null</c>',
returnsDescription: 'will always return <c>null</c>.'
}));

enumClass.add(new Attribute(TypeConverterAttribute, { parameters: [new LiteralExpression(`typeof(${converterClass})`)] }));

}
}
}
Loading

0 comments on commit 67674b2

Please sign in to comment.