public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst) { // SKIP // Apparently one can add keywords with [System.Management.Automation.Language.DynamicKeyword]::AddKeyword. // This won't work in static analysis. // I've never seen a dynamic keyword in the wild yet anyway. // Update: it appears in DSC, dynamic keywords are used: // Example to test: Configuration cnf { Import-DscResource -Module nx; Node 'lx.a.com' { nxFile ExampleFile { DestinationPath = '/tmp/example'; Contents = "hello world `n"; Ensure = 'Present'; Type = 'File'; } } }; cnf -OutputPath:'C:\temp' AstExplainer(dynamicKeywordStatementAst); return(base.VisitDynamicKeywordStatement(dynamicKeywordStatementAst)); }
public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst) { return(this.VisitDslExpression(dynamicKeywordStatementAst.CommandElements, dynamicKeywordStatementAst.Parent, dynamicKeywordStatementAst.Extent)); }
/// <summary/> public virtual object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { return null; }
public object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { return(false); }
public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst ast) { return(Check(ast)); }
public object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { throw PSTraceSource.NewArgumentException(nameof(dynamicKeywordAst)); }
/// <summary/> public virtual AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst) => DefaultVisit(dynamicKeywordStatementAst);
/// <summary> /// Generate auto complete results for identifier within configuration. /// Results are generated based on DynamicKeywords matches given identifier. /// For example, following "Fi" matches "File", and "Us" matches "User" /// /// Configuration /// { /// Fi^ /// Node("TargetMachine") /// { /// Us^ /// } /// } /// /// </summary> /// <param name="completionContext"></param> /// <param name="configureAst"></param> /// <param name="keywordAst"></param> /// <param name="matched"></param> /// <returns></returns> private List<CompletionResult> GetResultForIdentifierInConfiguration( CompletionContext completionContext, ConfigurationDefinitionAst configureAst, DynamicKeywordStatementAst keywordAst, out bool matched) { List<CompletionResult> results = null; matched = false; #if CORECLR // Microsoft.PowerShell.DesiredStateConfiguration is not in CORE CLR results = new List<CompletionResult>(); #else IEnumerable<DynamicKeyword> keywords = configureAst.DefinedKeywords.Where( k => // Node is special case, legal in both Resource and Meta configuration String.Compare(k.Keyword, @"Node", StringComparison.OrdinalIgnoreCase) == 0 || ( // Check compatibility between Resource and Configuration Type k.IsCompatibleWithConfigurationType(configureAst.ConfigurationType) && !DynamicKeyword.IsHiddenKeyword(k.Keyword) && !k.IsReservedKeyword ) ); if (keywordAst != null && completionContext.CursorPosition.Offset < keywordAst.Extent.EndOffset) keywords = keywordAst.Keyword.GetAllowedKeywords(keywords); if (keywords != null && keywords.Any()) { string commandName = (completionContext.WordToComplete ?? String.Empty) + "*"; var wildcardPattern = WildcardPattern.Get(commandName, WildcardOptions.IgnoreCase | WildcardOptions.CultureInvariant); // Filter by name var matchedResults = keywords.Where(k => wildcardPattern.IsMatch(k.Keyword)); if (matchedResults == null || !matchedResults.Any()) { // Fallback to all legal keywords in the configuration statement matchedResults = keywords; } else { matched = true; } foreach (var keyword in matchedResults) { string usageString = Microsoft.PowerShell.DesiredStateConfiguration.Internal.DscClassCache.GetDSCResourceUsageString(keyword); if (results == null) { results = new List<CompletionResult>(); } results.Add(new CompletionResult( keyword.Keyword, keyword.Keyword, CompletionResultType.DynamicKeyword, usageString)); } } #endif return results; }
object ICustomAstVisitor2.VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) => ProcessRewriter(VisitDynamicKeywordStatement, dynamicKeywordAst);
public virtual StatementAst VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { return(new DynamicKeywordStatementAst( dynamicKeywordAst.Extent, dynamicKeywordAst.CommandElements?.RewriteAll(this, SyntaxKind.CommandElement))); }
public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst) { return this.VisitDslExpression(dynamicKeywordStatementAst.CommandElements, dynamicKeywordStatementAst.Parent, dynamicKeywordStatementAst.Extent); }
public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst) { return(Visit(dynamicKeywordStatementAst)); }
public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst) => VisitAst(dynamicKeywordStatementAst);
/// <summary> /// Parse a dynamic keyword statement which will be either of the form /// keyword [parameters] [name] { a=1; b=2; } # constructor with properties /// or /// keyword [parameters] [name] { ... } # constructor with a simple body. /// or keywordcommand parameters /// This custom keyword does not introduce a new AST node type. Instead it generates a /// CommandAst that calls a PowerShell command to implement the keyword's logic. /// This command has one of two signatures: /// keywordImplCommand /// </summary> /// <param name="functionName">The name of the function to invoke</param> /// <param name="keywordData">The data for this keyword definition</param> /// <returns></returns> private StatementAst DynamicKeywordStatementRule(Token functionName, DynamicKeyword keywordData) { ////////////////////////////////////////////////////////////////////////////////// // If a custom action was provided. then invoke it ////////////////////////////////////////////////////////////////////////////////// if (keywordData.PreParse != null) { try { ParseError[] errors = keywordData.PreParse(keywordData); if (errors != null && errors.Length > 0) { foreach (var e in errors) { ReportError(e); } } } catch (Exception e) { ReportError(functionName.Extent, () => ParserStrings.DynamicKeywordPreParseException, keywordData.ResourceName, e.ToString()); return null; } } if (keywordData.IsReservedKeyword) { // ErrorRecovery: eat the token ReportError(functionName.Extent, () => ParserStrings.UnsupportedReservedKeyword, keywordData.Keyword); return null; } if (keywordData.HasReservedProperties) { // ErrorRecovery: eat the token ReportError(functionName.Extent, () => ParserStrings.UnsupportedReservedProperty, "'Require', 'Trigger', 'Notify', 'Before', 'After' and 'Subscribe'"); return null; } string elementName = string.Empty; DynamicKeywordStatementAst dynamicKeywordAst; if (keywordData.BodyMode == DynamicKeywordBodyMode.Command) { UngetToken(functionName); dynamicKeywordAst = (DynamicKeywordStatementAst)CommandRule(forDynamicKeyword: true); dynamicKeywordAst.Keyword = keywordData; dynamicKeywordAst.FunctionName = functionName; } else { SkipNewlines(); // The expression that returns the resource name or names. ExpressionAst instanceName = null; Token nameToken = NextToken(); if (nameToken.Kind == TokenKind.EndOfInput) { UngetToken(nameToken); if (keywordData.NameMode == DynamicKeywordNameMode.NameRequired || keywordData.NameMode == DynamicKeywordNameMode.SimpleNameRequired) { ReportIncompleteInput(After(functionName), () => ParserStrings.RequiredNameOrExpressionMissing); } else { // Name not required so report missing brace ReportIncompleteInput(After(functionName.Extent), () => ParserStrings.MissingBraceInObjectDefinition); } return null; } // If it's an lcurly, then no name was provided, and we skip to the body processing Token lCurly = null; if (nameToken.Kind == TokenKind.LCurly) { lCurly = nameToken; if (keywordData.NameMode == DynamicKeywordNameMode.NameRequired || keywordData.NameMode == DynamicKeywordNameMode.SimpleNameRequired) { ReportError(After(functionName), () => ParserStrings.RequiredNameOrExpressionMissing); UngetToken(nameToken); return null; } } else if (nameToken.Kind == TokenKind.Identifier || nameToken.Kind == TokenKind.DynamicKeyword) { if (keywordData.NameMode == DynamicKeywordNameMode.NoName) { ReportError(After(functionName), () => ParserStrings.UnexpectedNameForType, functionName.Text, nameToken.Text); UngetToken(nameToken); return null; } // If it's an identifier then this is the name for the data object elementName = nameToken.Text; // If only a simple name is allowed, then the string must be non-null. if ((keywordData.NameMode == DynamicKeywordNameMode.SimpleNameRequired || keywordData.NameMode == DynamicKeywordNameMode.SimpleOptionalName) && string.IsNullOrEmpty(elementName)) { ReportIncompleteInput(After(functionName), () => ParserStrings.RequiredNameOrExpressionMissing); UngetToken(nameToken); return null; } } else { // see if an expression was provided instead of a bare word... UngetToken(nameToken); instanceName = GetSingleCommandArgument(CommandArgumentContext.CommandName); if (instanceName == null) { if (keywordData.NameMode == DynamicKeywordNameMode.SimpleNameRequired || keywordData.NameMode == DynamicKeywordNameMode.SimpleOptionalName) { ReportError(After(functionName), () => ParserStrings.RequiredNameOrExpressionMissing); } else { // It wasn't an '{' and it wasn't a name expression so it's a unexpected token. ReportError(After(functionName), () => ParserStrings.UnexpectedToken, nameToken.Text); } return null; } // Ok, we got a name expression, but we're expecting no name, so it's and error. if (keywordData.NameMode == DynamicKeywordNameMode.NoName) { ReportError(After(functionName), () => ParserStrings.UnexpectedNameForType, functionName.Text, instanceName.ToString()); return null; } // We were expecting a simple name so report an error if (keywordData.NameMode == DynamicKeywordNameMode.SimpleNameRequired || keywordData.NameMode == DynamicKeywordNameMode.SimpleOptionalName) { // If no match, then this is an incomplete token BUGBUG fix message ReportError(nameToken.Extent, () => ParserStrings.UnexpectedToken, nameToken.Text); return null; } } // If we didn't get a resource expression AST, then we need to build one out of the // name that was specified. It may be the case that we don't have // a resource name in which case it will be the empty string. Even in the cases were // we aren't expecting a name, we still do this so that the signature of the implementing function remains // the same. ExpressionAst originalInstanceName = instanceName; if (instanceName == null) { instanceName = new StringConstantExpressionAst(nameToken.Extent, elementName, StringConstantType.BareWord); } SkipNewlines(); // // Now look for the body of the data statement. // if (lCurly == null) { lCurly = NextToken(); if (lCurly.Kind == TokenKind.EndOfInput) { UngetToken(lCurly); ReportIncompleteInput(After(functionName.Extent), () => ParserStrings.MissingBraceInObjectDefinition); // Preserve the name expression for tab completion return originalInstanceName == null ? null : new ErrorStatementAst(ExtentOf(functionName, originalInstanceName), GetNestedErrorAsts(originalInstanceName)); } if (lCurly.Kind != TokenKind.LCurly) { // We need to generate a reasonable error message for this case: // // Configuration C { // node $AllNode.NodeName{ # There is no space before curly, and we are converting scriptblock to and argument to call 'NodeName' // ... // } // } # we don't want to simple report an unexpected token here, it would be super-confusing. InvokeMemberExpressionAst instanceInvokeMemberExpressionAst = instanceName as InvokeMemberExpressionAst; if (instanceInvokeMemberExpressionAst != null && instanceInvokeMemberExpressionAst.Arguments.Count == 1 && instanceInvokeMemberExpressionAst.Arguments[0] is ScriptBlockExpressionAst && // the last condition checks that there is no space between "method" name and '{' instanceInvokeMemberExpressionAst.Member.Extent.EndOffset == instanceInvokeMemberExpressionAst.Arguments[0].Extent.StartOffset) { ReportError(LastCharacterOf(instanceInvokeMemberExpressionAst.Member.Extent), () => ParserStrings.UnexpectedTokenInDynamicKeyword, functionName.Text); } else { ReportError(lCurly.Extent, () => ParserStrings.UnexpectedToken, lCurly.Text); } if (lCurly.Kind == TokenKind.Dot && originalInstanceName != null && lCurly.Extent.StartOffset == originalInstanceName.Extent.EndOffset) { // Generate more useful ast for tab-completing extension methods on special DSC collection variables // e.g. configuration foo { node $AllNodes.<tab> IScriptExtent errorExtent = ExtentOf(originalInstanceName, lCurly); var errorExpr = new ErrorExpressionAst(errorExtent); var memberExpr = new MemberExpressionAst(originalInstanceName.Extent, originalInstanceName, errorExpr, @static: false); return new ErrorStatementAst(errorExtent, new[] { memberExpr }); } UngetToken(lCurly); // Preserve the name expression for tab completion return originalInstanceName == null ? null : new ErrorStatementAst(ExtentOf(functionName, originalInstanceName), GetNestedErrorAsts(originalInstanceName)); } } // // The keyword data is used to see // if a scriptblock or a hashtable is expected. // ExpressionAst body = null; if (keywordData.BodyMode == DynamicKeywordBodyMode.ScriptBlock) { var oldInConfiguraiton = _inConfiguration; try { _inConfiguration = false; body = ScriptBlockExpressionRule(lCurly); } finally { _inConfiguration = oldInConfiguraiton; } } else if (keywordData.BodyMode == DynamicKeywordBodyMode.Hashtable) { // Resource property value could be set to nested DSC resources except Script resource bool isScriptResource = String.Compare(functionName.Text, @"Script", StringComparison.OrdinalIgnoreCase) == 0; try { if (isScriptResource) DynamicKeyword.Push(); body = HashExpressionRule(lCurly, true /* parsingSchemaElement */); } finally { if (isScriptResource) DynamicKeyword.Pop(); } } // commandast // elements: instancename/dynamickeyword/hashtable or scripblockexpress if (body == null) { // Failed to read the statement body ReportIncompleteInput(After(lCurly), () => ParserStrings.MissingStatementAfterKeyword, keywordData.Keyword); // Preserve the name expression for tab completion return originalInstanceName == null ? null : new ErrorStatementAst(ExtentOf(functionName, originalInstanceName), GetNestedErrorAsts(originalInstanceName)); } ////////////////////////////////////////////////////////////////////////// // The statement is now fully parsed ////////////////////////////////////////////////////////////////////////// // // Create DynamicKeywordStatementAst // Collection<CommandElementAst> commandElements = new Collection<CommandElementAst> { new StringConstantExpressionAst(functionName.Extent, functionName.Text, StringConstantType.BareWord), (ExpressionAst)instanceName.Copy(), (ExpressionAst)body.Copy() }; Token nextToken = NextToken(); IScriptExtent dynamicKeywordExtent = ExtentOf(functionName, Before(nextToken)); UngetToken(nextToken); dynamicKeywordAst = new DynamicKeywordStatementAst(dynamicKeywordExtent, commandElements) { Keyword = keywordData, LCurly = lCurly, FunctionName = functionName, InstanceName = instanceName, OriginalInstanceName = originalInstanceName, BodyExpression = body, ElementName = elementName, }; } ////////////////////////////////////////////////////////////////////////////////// // If a custom action was provided. then invoke it ////////////////////////////////////////////////////////////////////////////////// if (keywordData.PostParse != null) { try { ParseError[] errors = keywordData.PostParse(dynamicKeywordAst); if (errors != null && errors.Length > 0) { foreach (var e in errors) { ReportError(e); } } } catch (Exception e) { ReportError(functionName.Extent, () => ParserStrings.DynamicKeywordPostParseException, keywordData.Keyword, e.ToString()); return null; } } return dynamicKeywordAst; }
public object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { if (dynamicKeywordAst.Keyword.MetaStatement) { return Expression.Empty(); } return this.VisitPipeline(dynamicKeywordAst.GenerateCommandCallPipelineAst()); }
/// <summary> /// Find the configuration statement contains current cursor /// </summary> /// <param name="cursorPosition"></param> /// <param name="ast"></param> /// <param name="keywordAst"></param> /// <returns></returns> private ConfigurationDefinitionAst GetAncestorConfigurationAstAndKeywordAst( IScriptPosition cursorPosition, Ast ast, out DynamicKeywordStatementAst keywordAst) { ConfigurationDefinitionAst configureAst = Ast.GetAncestorConfigurationDefinitionAstAndDynamicKeywordStatementAst(ast, out keywordAst); // Find the configuration statement contains current cursor // Note: cursorPosition.Offset < configureAst.Extent.EndOffset means cursor locates inside the configuration // cursorPosition.Offset = configureAst.Extent.EndOffset means cursor locates at the end of the configuration while (configureAst != null && cursorPosition.Offset > configureAst.Extent.EndOffset) { configureAst = Ast.GetAncestorAst<ConfigurationDefinitionAst>(configureAst.Parent); } return configureAst; }
// This function is called after parsing the Import-DscResource keyword and it's arguments, but before parsing // anything else. // // private static ParseError[] ImportResourcePostParse(DynamicKeywordStatementAst kwAst) { var elements = Ast.CopyElements(kwAst.CommandElements); Diagnostics.Assert(elements[0] is StringConstantExpressionAst && ((StringConstantExpressionAst)elements[0]).Value.Equals("Import-DscResource", StringComparison.OrdinalIgnoreCase), "Incorrect ast for expected keyword"); var commandAst = new CommandAst(kwAst.Extent, elements, TokenKind.Unknown, null); const string nameParam = "Name"; const string moduleNameParam = "ModuleName"; const string moduleVersionParam = "ModuleVersion"; StaticBindingResult bindingResult = StaticParameterBinder.BindCommand(commandAst, false); var errorList = new List<ParseError>(); foreach (var bindingException in bindingResult.BindingExceptions.Values) { errorList.Add(new ParseError(bindingException.CommandElement.Extent, "ParameterBindingException", bindingException.BindingException.Message)); } ParameterBindingResult moduleNameBindingResult = null; ParameterBindingResult resourceNameBindingResult = null; ParameterBindingResult moduleVersionBindingResult = null; foreach (var binding in bindingResult.BoundParameters) { // Error case when positional parameter values are specified var boundParameterName = binding.Key; var parameterBindingResult = binding.Value; if (boundParameterName.All(char.IsDigit)) { errorList.Add(new ParseError(parameterBindingResult.Value.Extent, "ImportDscResourcePositionalParamsNotSupported", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourcePositionalParamsNotSupported))); continue; } if (nameParam.StartsWith(boundParameterName, StringComparison.OrdinalIgnoreCase)) { resourceNameBindingResult = parameterBindingResult; } else if (moduleNameParam.StartsWith(boundParameterName, StringComparison.OrdinalIgnoreCase)) { moduleNameBindingResult = parameterBindingResult; } else if (moduleVersionParam.StartsWith(boundParameterName, StringComparison.OrdinalIgnoreCase)) { moduleVersionBindingResult = parameterBindingResult; } else { errorList.Add(new ParseError(parameterBindingResult.Value.Extent, "ImportDscResourceNeedParams", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); } } if (errorList.Count == 0 && moduleNameBindingResult == null && resourceNameBindingResult == null) { errorList.Add(new ParseError(kwAst.Extent, "ImportDscResourceNeedParams", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); } // Check here if Version is specified but modulename is not specified if (moduleVersionBindingResult != null && moduleNameBindingResult == null) { // only add this error again to the error list if resources is not null // if resources and modules are both null we have already added this error in collection // we do not want to do this twice. since we are giving same error ImportDscResourceNeedParams in both cases // once we have different error messages for 2 scenarios we can remove this check if (resourceNameBindingResult != null) { errorList.Add(new ParseError(kwAst.Extent, "ImportDscResourceNeedModuleNameWithModuleVersion", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); } } string[] resourceNames = null; if (resourceNameBindingResult != null) { object resourceName = null; if (!IsConstantValueVisitor.IsConstant(resourceNameBindingResult.Value, out resourceName, true, true) || !LanguagePrimitives.TryConvertTo(resourceName, out resourceNames)) { errorList.Add(new ParseError(resourceNameBindingResult.Value.Extent, "RequiresInvalidStringArgument", string.Format(CultureInfo.CurrentCulture, ParserStrings.RequiresInvalidStringArgument, nameParam))); } } System.Version moduleVersion = null; if (moduleVersionBindingResult != null) { object moduleVer = null; if (!IsConstantValueVisitor.IsConstant(moduleVersionBindingResult.Value, out moduleVer, true, true)) { errorList.Add(new ParseError(moduleVersionBindingResult.Value.Extent, "RequiresArgumentMustBeConstant", ParserStrings.RequiresArgumentMustBeConstant)); } if (moduleVer is double) { // this happens in case -ModuleVersion 1.0, then use extent text for that. // The better way to do it would be define static binding API against CommandInfo, that holds information about parameter types. // This way, we can avoid this ugly special-casing and say that -ModuleVersion has type [System.Version]. moduleVer = moduleVersionBindingResult.Value.Extent.Text; } if (!LanguagePrimitives.TryConvertTo(moduleVer, out moduleVersion)) { errorList.Add(new ParseError(moduleVersionBindingResult.Value.Extent, "RequiresVersionInvalid", ParserStrings.RequiresVersionInvalid)); } } ModuleSpecification[] moduleSpecifications = null; if (moduleNameBindingResult != null) { object moduleName = null; if (!IsConstantValueVisitor.IsConstant(moduleNameBindingResult.Value, out moduleName, true, true)) { errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "RequiresArgumentMustBeConstant", ParserStrings.RequiresArgumentMustBeConstant)); } if (LanguagePrimitives.TryConvertTo(moduleName, out moduleSpecifications)) { // if resourceNames are specified then we can not specify multiple modules name if (moduleSpecifications != null && moduleSpecifications.Length > 1 && resourceNames != null) { errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "ImportDscResourceMultipleModulesNotSupportedWithName", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceMultipleModulesNotSupportedWithName))); } // if moduleversion is specified then we can not specify multiple modules name if (moduleSpecifications != null && moduleSpecifications.Length > 1 && moduleVersion != null) { errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "ImportDscResourceMultipleModulesNotSupportedWithVersion", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); } // if moduleversion is specified then we can not specify another version in modulespecification object of ModuleName if (moduleSpecifications != null && (moduleSpecifications[0].Version != null || moduleSpecifications[0].MaximumVersion != null) && moduleVersion != null) { errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "ImportDscResourceMultipleModuleVersionsNotSupported", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceNeedParams))); } // If moduleVersion is specified we have only one module Name in valid scenario // So update it's version property in module specification object that will be used to load modules if (moduleSpecifications != null && moduleSpecifications[0].Version == null && moduleSpecifications[0].MaximumVersion == null && moduleVersion != null) { moduleSpecifications[0].Version = moduleVersion; } } else { errorList.Add(new ParseError(moduleNameBindingResult.Value.Extent, "RequiresInvalidStringArgument", string.Format(CultureInfo.CurrentCulture, ParserStrings.RequiresInvalidStringArgument, moduleNameParam))); } } if (errorList.Count == 0) { // No errors, try to load the resources LoadResourcesFromModule(kwAst.Extent, moduleSpecifications, resourceNames, errorList); } return errorList.ToArray(); }
public override StatementAst VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) => VisitStatement(base.VisitDynamicKeywordStatement(dynamicKeywordAst));
// This function performs semantic checks for Import-DscResource private static ParseError[] ImportResourceCheckSemantics(DynamicKeywordStatementAst kwAst) { List<ParseError> errorList = null; var keywordAst = Ast.GetAncestorAst<DynamicKeywordStatementAst>(kwAst.Parent); while (keywordAst != null) { if (keywordAst.Keyword.Keyword.Equals("Node")) { if (errorList == null) { errorList = new List<ParseError>(); } errorList.Add(new ParseError(kwAst.Extent, "ImportDscResourceInsideNode", string.Format(CultureInfo.CurrentCulture, ParserStrings.ImportDscResourceInsideNode))); break; } keywordAst = Ast.GetAncestorAst<DynamicKeywordStatementAst>(keywordAst.Parent); } if (errorList != null) { return errorList.ToArray(); } else { return null; } }
public object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { throw new System.NotImplementedException(); }
// This function performs semantic checks for all DSC Resources keywords. private static ParseError[] CheckMandatoryPropertiesPresent(DynamicKeywordStatementAst kwAst) { HashSet<string> mandatoryPropertiesNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase); foreach (var pair in kwAst.Keyword.Properties) { if (pair.Value.Mandatory) { mandatoryPropertiesNames.Add(pair.Key); } } // by design mandatoryPropertiesNames are not empty at this point: // every resource must have at least one Key property. HashtableAst hashtableAst = null; foreach (var ast in kwAst.CommandElements) { hashtableAst = ast as HashtableAst; if (hashtableAst != null) { break; } } if (hashtableAst == null) { // nothing to validate return null; } foreach (var pair in hashtableAst.KeyValuePairs) { object evalResultObject; if (IsConstantValueVisitor.IsConstant(pair.Item1, out evalResultObject, forAttribute: false, forRequires: false)) { var presentName = evalResultObject as string; if (presentName != null) { if (mandatoryPropertiesNames.Remove(presentName) && mandatoryPropertiesNames.Count == 0) { // optimization, once all mandatory properties are specified, we can safely exit. return null; } } } } if (mandatoryPropertiesNames.Count > 0) { ParseError[] errors = new ParseError[mandatoryPropertiesNames.Count]; var extent = kwAst.CommandElements[0].Extent; int i = 0; foreach (string name in mandatoryPropertiesNames) { errors[i] = new ParseError(extent, "MissingValueForMandatoryProperty", string.Format(CultureInfo.CurrentCulture, ParserStrings.MissingValueForMandatoryProperty, kwAst.Keyword.Keyword, kwAst.Keyword.Properties.First( p => StringComparer.OrdinalIgnoreCase.Equals(p.Value.Name, name)).Value.TypeConstraint, name)); i++; } return errors; } return null; }
/// <summary/> public virtual object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { return(null); }
public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst) { ////////////////////////////////////////////////////////////////////////////////// // If a custom action was provided. then invoke it ////////////////////////////////////////////////////////////////////////////////// if (dynamicKeywordStatementAst.Keyword.SemanticCheck != null) { try { ParseError[] errors = dynamicKeywordStatementAst.Keyword.SemanticCheck(dynamicKeywordStatementAst); if (errors != null && errors.Length > 0) errors.ToList().ForEach(e => _parser.ReportError(e)); } catch (Exception e) { _parser.ReportError(dynamicKeywordStatementAst.Extent, () => ParserStrings.DynamicKeywordSemanticCheckException, dynamicKeywordStatementAst.Keyword.ResourceName, e.ToString()); } } DynamicKeyword keyword = dynamicKeywordStatementAst.Keyword; HashtableAst hashtable = dynamicKeywordStatementAst.BodyExpression as HashtableAst; if (hashtable != null) { // // If it's a hash table, validate that only valid members have been specified. // foreach (var keyValueTuple in hashtable.KeyValuePairs) { var propName = keyValueTuple.Item1 as StringConstantExpressionAst; if (propName == null) { _parser.ReportError(keyValueTuple.Item1.Extent, () => ParserStrings.ConfigurationInvalidPropertyName, dynamicKeywordStatementAst.FunctionName.Extent, keyValueTuple.Item1.Extent); } else if (!keyword.Properties.ContainsKey(propName.Value)) { _parser.ReportError(propName.Extent, () => ParserStrings.InvalidInstanceProperty, propName.Value, string.Join("', '", keyword.Properties.Keys.OrderBy(key => key, StringComparer.OrdinalIgnoreCase))); } } } // // Check compatibility between DSC Resource and Configuration // ConfigurationDefinitionAst configAst = Ast.GetAncestorAst<ConfigurationDefinitionAst>(dynamicKeywordStatementAst); if (configAst != null) { StringConstantExpressionAst nameAst = dynamicKeywordStatementAst.CommandElements[0] as StringConstantExpressionAst; Diagnostics.Assert(nameAst != null, "nameAst should never be null"); if (!DscClassCache.SystemResourceNames.Contains(nameAst.Extent.Text.Trim())) { if (configAst.ConfigurationType == ConfigurationType.Meta && !dynamicKeywordStatementAst.Keyword.IsMetaDSCResource()) { _parser.ReportError(nameAst.Extent, () => ParserStrings.RegularResourceUsedInMetaConfig, nameAst.Extent.Text); } else if (configAst.ConfigurationType != ConfigurationType.Meta && dynamicKeywordStatementAst.Keyword.IsMetaDSCResource()) { _parser.ReportError(nameAst.Extent, () => ParserStrings.MetaConfigurationUsedInRegularConfig, nameAst.Extent.Text); } } } return AstVisitAction.Continue; }
/// <summary/> public virtual AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst) { return(AstVisitAction.Continue); }
/// <summary/> public virtual AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordStatementAst) { return AstVisitAction.Continue; }
public object VisitDynamicKeywordStatement(DynamicKeywordStatementAst dynamicKeywordAst) { return(AutomationNull.Value); }
public override AstVisitAction VisitDynamicKeywordStatement(DynamicKeywordStatementAst ast) { return Check(ast); }