diff --git a/src/System.Management.Automation/engine/parser/Compiler.cs b/src/System.Management.Automation/engine/parser/Compiler.cs index ee910e59ea..d160ea6149 100644 --- a/src/System.Management.Automation/engine/parser/Compiler.cs +++ b/src/System.Management.Automation/engine/parser/Compiler.cs @@ -733,6 +733,7 @@ namespace System.Management.Automation.Language } s_builtinAttributeGenerator.Add(typeof(CmdletBindingAttribute), NewCmdletBindingAttribute); + s_builtinAttributeGenerator.Add(typeof(ExperimentalAttribute), NewExperimentalAttribute); s_builtinAttributeGenerator.Add(typeof(ParameterAttribute), NewParameterAttribute); s_builtinAttributeGenerator.Add(typeof(OutputTypeAttribute), NewOutputTypeAttribute); s_builtinAttributeGenerator.Add(typeof(AliasAttribute), NewAliasAttribute); @@ -1069,6 +1070,9 @@ namespace System.Management.Automation.Language CallSite>.Create(PSConvertBinder.Get(typeof(ConfirmImpact))); private static readonly CallSite> s_attrArgToRemotingCapabilityConverter = CallSite>.Create(PSConvertBinder.Get(typeof(RemotingCapability))); + private static readonly CallSite> s_attrArgToExperimentActionConverter = + CallSite>.Create(PSConvertBinder.Get(typeof(ExperimentAction))); + private static readonly ConstantValueVisitor s_cvv = new ConstantValueVisitor { AttributeArgument = true }; private static void CheckNoPositionalArgs(AttributeAst ast) { @@ -1093,17 +1097,25 @@ namespace System.Management.Automation.Language } } + private static (string name, ExperimentAction action) GetFeatureNameAndAction(AttributeAst ast) + { + var argValue0 = ast.PositionalArguments[0].Accept(s_cvv); + var argValue1 = ast.PositionalArguments[1].Accept(s_cvv); + + var featureName = _attrArgToStringConverter.Target(_attrArgToStringConverter, argValue0); + var action = s_attrArgToExperimentActionConverter.Target(s_attrArgToExperimentActionConverter, argValue1); + return (featureName, action); + } + private static Attribute NewCmdletBindingAttribute(AttributeAst ast) { CheckNoPositionalArgs(ast); - var cvv = new ConstantValueVisitor { AttributeArgument = true }; - var result = new CmdletBindingAttribute(); foreach (var namedArg in ast.NamedArguments) { - var argValue = namedArg.Argument.Accept(cvv); + var argValue = namedArg.Argument.Accept(s_cvv); var argumentName = namedArg.ArgumentName; if (argumentName.Equals("DefaultParameterSetName", StringComparison.OrdinalIgnoreCase)) { @@ -1148,17 +1160,42 @@ namespace System.Management.Automation.Language return result; } + private static Attribute NewExperimentalAttribute(AttributeAst ast) + { + int positionalArgCount = ast.PositionalArguments.Count; + if (positionalArgCount != 2) + { + throw InterpreterError.NewInterpreterException(null, typeof(MethodException), ast.Extent, + "MethodCountCouldNotFindBest", ExtendedTypeSystem.MethodArgumentCountException, ".ctor", + positionalArgCount); + } + + var (name, action) = GetFeatureNameAndAction(ast); + return new ExperimentalAttribute(name, action); + } + private static Attribute NewParameterAttribute(AttributeAst ast) { - CheckNoPositionalArgs(ast); - - var cvv = new ConstantValueVisitor { AttributeArgument = true }; - - var result = new ParameterAttribute(); + ParameterAttribute result; + int positionalArgCount = ast.PositionalArguments.Count; + switch (positionalArgCount) + { + case 0: + result = new ParameterAttribute(); + break; + case 2: + var (name, action) = GetFeatureNameAndAction(ast); + result = new ParameterAttribute(name, action); + break; + default: + throw InterpreterError.NewInterpreterException(null, typeof(MethodException), ast.Extent, + "MethodCountCouldNotFindBest", ExtendedTypeSystem.MethodArgumentCountException, ".ctor", + positionalArgCount); + } foreach (var namedArg in ast.NamedArguments) { - var argValue = namedArg.Argument.Accept(cvv); + var argValue = namedArg.Argument.Accept(s_cvv); var argumentName = namedArg.ArgumentName; if (argumentName.Equals("Position", StringComparison.OrdinalIgnoreCase)) @@ -1214,8 +1251,6 @@ namespace System.Management.Automation.Language private static Attribute NewOutputTypeAttribute(AttributeAst ast) { - var cvv = new ConstantValueVisitor { AttributeArgument = true }; - OutputTypeAttribute result; if (ast.PositionalArguments.Count == 0) { @@ -1231,7 +1266,7 @@ namespace System.Management.Automation.Language } else { - var argValue = ast.PositionalArguments[0].Accept(cvv); + var argValue = ast.PositionalArguments[0].Accept(s_cvv); result = new OutputTypeAttribute(_attrArgToStringConverter.Target(_attrArgToStringConverter, argValue)); } } @@ -1244,7 +1279,7 @@ namespace System.Management.Automation.Language var typeArg = positionalArgument as TypeExpressionAst; args[i] = typeArg != null ? TypeOps.ResolveTypeName(typeArg.TypeName, typeArg.Extent) - : positionalArgument.Accept(cvv); + : positionalArgument.Accept(s_cvv); } if (args[0] is Type) @@ -1259,7 +1294,7 @@ namespace System.Management.Automation.Language foreach (var namedArg in ast.NamedArguments) { - var argValue = namedArg.Argument.Accept(cvv); + var argValue = namedArg.Argument.Accept(s_cvv); var argumentName = namedArg.ArgumentName; if (argumentName.Equals("ParameterSetName", StringComparison.OrdinalIgnoreCase)) @@ -1285,12 +1320,11 @@ namespace System.Management.Automation.Language { CheckNoNamedArgs(ast); - var cvv = new ConstantValueVisitor { AttributeArgument = true }; var args = new string[ast.PositionalArguments.Count]; for (int i = 0; i < ast.PositionalArguments.Count; i++) { args[i] = _attrArgToStringConverter.Target(_attrArgToStringConverter, - ast.PositionalArguments[i].Accept(cvv)); + ast.PositionalArguments[i].Accept(s_cvv)); } return new AliasAttribute(args); } @@ -1298,7 +1332,6 @@ namespace System.Management.Automation.Language private static Attribute NewValidateSetAttribute(AttributeAst ast) { ValidateSetAttribute result; - var cvv = new ConstantValueVisitor { AttributeArgument = true }; // 'ValidateSet([CustomGeneratorType], IgnoreCase=$false)' is supported in scripts. if (ast.PositionalArguments.Count == 1 && ast.PositionalArguments[0] is TypeExpressionAst generatorTypeAst) @@ -1322,7 +1355,7 @@ namespace System.Management.Automation.Language for (int i = 0; i < ast.PositionalArguments.Count; i++) { args[i] = _attrArgToStringConverter.Target(_attrArgToStringConverter, - ast.PositionalArguments[i].Accept(cvv)); + ast.PositionalArguments[i].Accept(s_cvv)); } result = new ValidateSetAttribute(args); @@ -1330,7 +1363,7 @@ namespace System.Management.Automation.Language foreach (var namedArg in ast.NamedArguments) { - var argValue = namedArg.Argument.Accept(cvv); + var argValue = namedArg.Argument.Accept(s_cvv); var argumentName = namedArg.ArgumentName; if (argumentName.Equals("IgnoreCase", StringComparison.OrdinalIgnoreCase)) { @@ -1395,17 +1428,16 @@ namespace System.Management.Automation.Language var delegateArgs = new object[totalArgCount + 1]; delegateArgs[0] = attributeType; - var cvv = new ConstantValueVisitor { AttributeArgument = true }; int i = 1; for (int index = 0; index < attributeAst.PositionalArguments.Count; index++) { var posArg = attributeAst.PositionalArguments[index]; - delegateArgs[i++] = posArg.Accept(cvv); + delegateArgs[i++] = posArg.Accept(s_cvv); } for (int index = 0; index < attributeAst.NamedArguments.Count; index++) { var namedArg = attributeAst.NamedArguments[index]; - delegateArgs[i++] = namedArg.Argument.Accept(cvv); + delegateArgs[i++] = namedArg.Argument.Accept(s_cvv); } try