public override AstVisitAction VisitCommand(CommandAst commandAst) { string commandName = commandAst?.GetCommandName(); if (commandName == null) { return(AstVisitAction.Continue); } if (_commandsToIgnore.Contains(commandName)) { return(AstVisitAction.Continue); } // Note: // The "right" way to eliminate user-defined commands would be to build // a list of: // - all functions defined above this point // - all modules imported // However, looking for imported modules could prove very expensive // and we would still miss things like assignments to the function: provider. // Instead, we look to see if a command of the given name is present in any // known profile, which is something of a hack. // This is not present in any known profiles, so assume it is user defined if (!_anyProfile.Runtime.Commands.ContainsKey(commandName)) { return(AstVisitAction.Continue); } // Check each target platform foreach (CompatibilityProfileData targetProfile in _compatibilityTargets) { // If the target has this command, everything is good if (targetProfile.Runtime.Commands.TryGetValue(commandName, out IReadOnlyList <CommandData> matchedCommands)) { // Now check that the parameters on the command are available on all target platforms CheckCommandInvocationParameters(targetProfile, commandName, commandAst, matchedCommands); continue; } var diagnostic = CommandCompatibilityDiagnostic.Create( commandName, targetProfile.Platform, commandAst.Extent, _analyzedFileName, _rule); _diagnosticAccumulator.Add(diagnostic); } return(AstVisitAction.Continue); }
private void CheckCommandInvocationParameters( CompatibilityProfileData targetProfile, string commandName, CommandAst commandAst, IEnumerable <CommandData> commandsToCheck) { // TODO: // Ideally we would go through each command and emulate the parameter binding algorithm // to work out what positions and what parameters will and won't work, // but this is very involved. // For now, we'll just check that the parameters exist for (int i = 0; i < commandAst.CommandElements.Count; i++) { CommandElementAst commandElement = commandAst.CommandElements[i]; if (!(commandElement is CommandParameterAst parameterAst)) { continue; } bool isGoodParam = false; foreach (CommandData command in commandsToCheck) { if ((command.Parameters != null && command.Parameters.ContainsKey(parameterAst.ParameterName)) || (command.IsCmdletBinding && targetProfile.Runtime.Common.Parameters.ContainsKey(parameterAst.ParameterName))) { isGoodParam = true; break; } } if (isGoodParam) { continue; } _diagnosticAccumulator.Add(CommandCompatibilityDiagnostic.CreateForParameter( parameterAst.ParameterName, commandName, targetProfile.Platform, parameterAst.Extent, _analyzedFileName, _rule)); } }