/// <summary> /// Adds each function definition as a /// </summary> /// <param name="functionDefinitionAst">A functionDefinitionAst object in the script's AST</param> /// <returns>A decision to stop searching if the right symbol was found, /// or a decision to continue if it wasn't found</returns> public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { IScriptExtent nameExtent = new ScriptExtent() { Text = functionDefinitionAst.Name, StartLineNumber = functionDefinitionAst.Extent.StartLineNumber, EndLineNumber = functionDefinitionAst.Extent.EndLineNumber, StartColumnNumber = functionDefinitionAst.Extent.StartColumnNumber, EndColumnNumber = functionDefinitionAst.Extent.EndColumnNumber }; SymbolType symbolType = functionDefinitionAst.IsWorkflow ? SymbolType.Workflow : SymbolType.Function; this.SymbolReferences.Add( new SymbolReference( symbolType, nameExtent)); return(AstVisitAction.Continue); }
/// <summary> /// Decides if the current function definition is a reference of the symbol being searched for. /// A reference of the symbol will be a of type SymbolType.Function and have the same name as the symbol /// </summary> /// <param name="functionDefinitionAst">A functionDefinitionAst in the script's AST</param> /// <returns>A visit action that continues the search for references</returns> public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { (int startColumnNumber, int startLineNumber) = GetStartColumnAndLineNumbersFromAst(functionDefinitionAst); IScriptExtent nameExtent = new ScriptExtent() { Text = functionDefinitionAst.Name, StartLineNumber = startLineNumber, EndLineNumber = startLineNumber, StartColumnNumber = startColumnNumber, EndColumnNumber = startColumnNumber + functionDefinitionAst.Name.Length }; if (symbolRef.SymbolType.Equals(SymbolType.Function) && nameExtent.Text.Equals(symbolRef.SymbolName, StringComparison.CurrentCultureIgnoreCase)) { this.FoundReferences.Add(new SymbolReference( SymbolType.Function, nameExtent)); } return(base.VisitFunctionDefinition(functionDefinitionAst)); }
public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { _currentMethod = new CodeMemberMethod(); _currentMethod.Name = functionDefinitionAst.Name; if (functionDefinitionAst.Parameters != null) { foreach (var parameter in functionDefinitionAst.Parameters) { _currentMethod.Parameters.Add(new CodeParameterDeclarationExpression(parameter.StaticType, parameter.Name.VariablePath.ToString())); } } _currentClass.Members.Add(_currentMethod); foreach (var statement in functionDefinitionAst.Body.EndBlock.Statements) { var code = Visit(statement); if (code is CodeStatement) { _currentMethod.Statements.Add(code as CodeStatement); } if (code is CodeMethodInvokeExpression) { _currentMethod.Statements.Add(new CodeExpressionStatement(code as CodeExpression)); } else if (code is CodeExpression) { _currentMethod.Statements.Add(code as CodeExpression); } } _currentMethod = null; return(unit); }
/// <summary> /// Visit function and checks that it has comment help /// </summary> /// <param name="funcAst"></param> /// <returns></returns> public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst funcAst) { if (funcAst == null) { return(AstVisitAction.SkipChildren); } if (exportedFunctions.Contains(funcAst.Name)) { if (funcAst.GetHelpContent() == null) { DiagnosticRecords.Add( new DiagnosticRecord( string.Format(CultureInfo.CurrentCulture, Strings.ProvideCommentHelpError, funcAst.Name), Helper.Instance.GetScriptExtentForFunctionName(funcAst), GetName(), DiagnosticSeverity.Information, fileName)); } } return(AstVisitAction.Continue); }
public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { throw new UnexpectedElementException(); }
// FunctionDefinitionAst Extension Methods // New Methods Available: // - CreateNodeFromAST(NodeDepth, NodePosition, Parent) => Creates a Node public static FunctionNode CreateNodeFromAst(this FunctionDefinitionAst _ast, int _depth, int _position, Node _parent, Tree _tree) { return(new FunctionNode(_ast, _depth, _position, _parent, _tree)); }
public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { return(false); }
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { FunctionCount += 1; return(AstVisitAction.Continue); }
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { Console.WriteLine("Visited an FunctionDefinitionAst."); Console.WriteLine(" " + functionDefinitionAst.ToString().Replace(Environment.NewLine, Environment.NewLine + " ")); return(AstVisitAction.Continue); }
public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) => null;
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst ast) { return(AstVisitAction.Continue); }
private static ImageListKind GetImageListKind(FunctionDefinitionAst funcDef) { //TODO: More image kinds here return(ImageListKind.Method); }
private static ImageListKind GetImageListKind(FunctionDefinitionAst funcDef) { return(ImageListKind.Method); }
public FunctionDefinitionEntryInfo(FunctionDefinitionAst functionDefinition) { _functionDefinition = functionDefinition; }
internal static Tuple <List <System.Management.Automation.Language.Token>, List <string> > GetHelpCommentTokens(IParameterMetadataProvider ipmp, Dictionary <Ast, System.Management.Automation.Language.Token[]> scriptBlockTokenCache) { int num; int num2; int num3; List <System.Management.Automation.Language.Token> commentBlock; Ast ast = (Ast)ipmp; Ast key = ast; while (key.Parent != null) { key = key.Parent; } System.Management.Automation.Language.Token[] tokenArray = null; scriptBlockTokenCache.TryGetValue(key, out tokenArray); if (tokenArray == null) { ParseError[] errorArray; Parser.ParseInput(key.Extent.Text, out tokenArray, out errorArray); scriptBlockTokenCache[key] = tokenArray; } FunctionDefinitionAst ast3 = ast as FunctionDefinitionAst; if (ast3 != null) { int tokenIndex = num = FirstTokenInExtent(tokenArray, ast.Extent, 0); commentBlock = GetPrecedingCommentBlock(tokenArray, tokenIndex, 2); if (IsCommentHelpText(commentBlock)) { return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num))); } num2 = FirstTokenInExtent(tokenArray, ast3.Body.Extent, 0) + 1; num3 = LastTokenInExtent(tokenArray, ast.Extent, tokenIndex); } else if (ast == key) { num2 = num = 0; num3 = tokenArray.Length - 1; } else { num2 = num = FirstTokenInExtent(tokenArray, ast.Extent, 0) - 1; num3 = LastTokenInExtent(tokenArray, ast.Extent, num2); } do { commentBlock = GetCommentBlock(tokenArray, ref num2); if (commentBlock.Count == 0) { goto Label_0195; } }while (!IsCommentHelpText(commentBlock)); if (ast == key) { NamedBlockAst endBlock = ((ScriptBlockAst)ast).EndBlock; if ((endBlock == null) || !endBlock.Unnamed) { return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num))); } StatementAst ast5 = endBlock.Statements.FirstOrDefault <StatementAst>(); if (ast5 is FunctionDefinitionAst) { int num5 = ast5.Extent.StartLineNumber - commentBlock.Last <System.Management.Automation.Language.Token>().Extent.EndLineNumber; if (num5 > 2) { return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num))); } goto Label_0195; } } return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num))); Label_0195: commentBlock = GetPrecedingCommentBlock(tokenArray, num3, tokenArray[num3].Extent.StartLineNumber); if (IsCommentHelpText(commentBlock)) { return(Tuple.Create <List <System.Management.Automation.Language.Token>, List <string> >(commentBlock, GetParameterComments(tokenArray, ipmp, num))); } return(null); }
private IEnumerable <ParameterAst> GetMandatoryParameters(FunctionDefinitionAst functionDefinitionAst) { return(functionDefinitionAst.GetParameterAsts()?.Where(IsParameterMandatory) ?? Enumerable.Empty <ParameterAst>()); }
public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { throw PSTraceSource.NewArgumentException("ast"); }
public virtual object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { VisitElement(functionDefinitionAst.Body); VisitElements(functionDefinitionAst.Parameters); return(functionDefinitionAst); }
/// <summary/> public virtual AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) => DefaultVisit(functionDefinitionAst);
private List <CorrectionExtent> GetCorrections( int whatIfIndex, int confirmIndex, ParameterAst[] parameterAsts, ParamBlockAst paramBlockAst, FunctionDefinitionAst funcDefnAst) { var filePath = funcDefnAst.Extent.File; var correctionExtents = new List <CorrectionExtent>(); if (paramBlockAst != null) { if (whatIfIndex != -1) { correctionExtents.Add(GetCorrectionToRemoveParam(whatIfIndex, parameterAsts)); } if (confirmIndex != -1) { correctionExtents.Add(GetCorrectionToRemoveParam(confirmIndex, parameterAsts)); } AttributeAst attributeAst = paramBlockAst.GetCmdletBindingAttributeAst(); // check if it has cmdletbinding attribute if (attributeAst != null) { NamedAttributeArgumentAst shouldProcessAst = attributeAst.GetSupportsShouldProcessAst(); if (shouldProcessAst != null) { ExpressionAst argAst; if (!shouldProcessAst.GetValue(out argAst) && argAst != null) { // SupportsShouldProcess is set to something other than $true. // Set it to $true correctionExtents.Add(GetCorrectionsToSetShouldProcessToTrue(argAst)); } } else { // add supportsshouldprocess to the attribute correctionExtents.Add(GetCorrectionToAddShouldProcess(attributeAst)); } } else { // has no cmdletbinding attribute // hence, add the attribute and supportsshouldprocess argument correctionExtents.Add(GetCorrectionToAddAttribute(paramBlockAst)); } } else { // function doesn't have param block // remove the parameter list // and create an equivalent param block // add cmdletbinding attribute and add supportsshouldprocess to it. correctionExtents.Add(GetCorrectionToRemoveFuncParamDecl(funcDefnAst, ast, tokens)); correctionExtents.Add(GetCorrectionToAddParamBlock(funcDefnAst, parameterAsts)); } // This is how we handle multiple edits- // create separate edits // apply those edits to the original script extent // and then give the corrected extent as suggested correction. // sort in descending order of start position correctionExtents.Sort((x, y) => { var xRange = (Range)x; var yRange = (Range)y; return(xRange.Start < yRange.Start ? 1 : (xRange.Start == yRange.Start ? 0 : -1)); }); var editableText = new EditableText(funcDefnAst.Extent.Text); var funcDefAstStartPos = funcDefnAst.Extent.ToRange().Start; foreach (var correctionExtent in correctionExtents) { var shiftedCorrectionExtent = Normalize(funcDefAstStartPos, correctionExtent); editableText.ApplyEdit(shiftedCorrectionExtent); } var result = new List <CorrectionExtent>(); result.Add( new CorrectionExtent( funcDefnAst.Extent.StartLineNumber, funcDefnAst.Extent.EndLineNumber, funcDefnAst.Extent.StartColumnNumber, funcDefnAst.Extent.EndColumnNumber, editableText.ToString(), funcDefnAst.Extent.File)); return(result); }
public object VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { Console.WriteLine("Visited an FunctionDefinitionAst."); return(functionDefinitionAst); }
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { // TODO: add function definition explanation AstExplainer(functionDefinitionAst); return(base.VisitFunctionDefinition(functionDefinitionAst)); }
/// <summary> /// Visit function and checks that it is a cmdlet. If yes, then checks that any object returns must have a type declared /// in the output type (the only exception is if the type is object) /// </summary> /// <param name="funcAst"></param> /// <returns></returns> public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst funcAst) { if (funcAst == null || funcAst.Body == null || funcAst.Body.ParamBlock == null || funcAst.Body.ParamBlock.Attributes == null || funcAst.Body.ParamBlock.Attributes.Count == 0 || !funcAst.Body.ParamBlock.Attributes.Any(attr => attr.TypeName.GetReflectionType() == typeof(CmdletBindingAttribute))) { return(AstVisitAction.Continue); } HashSet <string> outputTypes = new HashSet <string>(); foreach (AttributeAst attrAst in funcAst.Body.ParamBlock.Attributes) { if (attrAst.TypeName != null && attrAst.TypeName.GetReflectionType() == typeof(OutputTypeAttribute) && attrAst.PositionalArguments != null) { foreach (ExpressionAst expAst in attrAst.PositionalArguments) { if (expAst is StringConstantExpressionAst) { Type type = Type.GetType((expAst as StringConstantExpressionAst).Value); if (type != null) { outputTypes.Add(type.FullName); } } else { TypeExpressionAst typeAst = expAst as TypeExpressionAst; if (typeAst != null && typeAst.TypeName != null) { if (typeAst.TypeName.GetReflectionType() != null) { outputTypes.Add(typeAst.TypeName.GetReflectionType().FullName); } else { outputTypes.Add(typeAst.TypeName.FullName); } } } } } } #if PSV3 List <Tuple <string, StatementAst> > returnTypes = FindPipelineOutput.OutputTypes(funcAst); #else List <Tuple <string, StatementAst> > returnTypes = FindPipelineOutput.OutputTypes(funcAst, _classes); #endif HashSet <string> specialTypes = new HashSet <string>(StringComparer.OrdinalIgnoreCase); specialTypes.Add(typeof(Unreached).FullName); specialTypes.Add(typeof(Undetermined).FullName); specialTypes.Add(typeof(object).FullName); specialTypes.Add(typeof(void).FullName); specialTypes.Add(typeof(PSCustomObject).FullName); specialTypes.Add(typeof(PSObject).FullName); foreach (Tuple <string, StatementAst> returnType in returnTypes) { string typeName = returnType.Item1; if (String.IsNullOrEmpty(typeName) || specialTypes.Contains(typeName) || outputTypes.Contains(typeName, StringComparer.OrdinalIgnoreCase)) { continue; } else { DiagnosticRecords.Add(new DiagnosticRecord(string.Format(CultureInfo.CurrentCulture, Strings.UseOutputTypeCorrectlyError, funcAst.Name, typeName), returnType.Item2.Extent, GetName(), DiagnosticSeverity.Information, fileName)); } } return(AstVisitAction.Continue); }
public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst ast) { return(DoNextAction(ast)); }
public async Task <CommentHelpRequestResult> Handle(CommentHelpRequestParams request, CancellationToken cancellationToken) { var result = new CommentHelpRequestResult(); if (!_workspaceService.TryGetFile(request.DocumentUri, out ScriptFile scriptFile)) { return(result); } int triggerLine = (int)request.TriggerPosition.Line + 1; FunctionDefinitionAst functionDefinitionAst = _symbolsService.GetFunctionDefinitionForHelpComment( scriptFile, triggerLine, out string helpLocation); if (functionDefinitionAst == null) { return(result); } IScriptExtent funcExtent = functionDefinitionAst.Extent; string funcText = funcExtent.Text; if (helpLocation.Equals("begin")) { // check if the previous character is `<` because it invalidates // the param block the follows it. IList <string> lines = ScriptFile.GetLinesInternal(funcText); int relativeTriggerLine0b = triggerLine - funcExtent.StartLineNumber; if (relativeTriggerLine0b > 0 && lines[relativeTriggerLine0b].IndexOf("<", StringComparison.OrdinalIgnoreCase) > -1) { lines[relativeTriggerLine0b] = string.Empty; } funcText = string.Join("\n", lines); } List <ScriptFileMarker> analysisResults = await _analysisService.GetSemanticMarkersAsync( funcText, AnalysisService.GetCommentHelpRuleSettings( enable: true, exportedOnly: false, blockComment: request.BlockComment, vscodeSnippetCorrection: true, placement: helpLocation)); string helpText = analysisResults?.FirstOrDefault()?.Correction?.Edits[0].Text; if (helpText == null) { return(result); } result.Content = ScriptFile.GetLinesInternal(helpText).ToArray(); if (helpLocation != null && !helpLocation.Equals("before", StringComparison.OrdinalIgnoreCase)) { // we need to trim the leading `{` and newline when helpLocation=="begin" // we also need to trim the leading newline when helpLocation=="end" result.Content = result.Content.Skip(1).ToArray(); } return(result); }
public override StatementAst VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) => VisitStatement(base.VisitFunctionDefinition(functionDefinitionAst));
/// <summary> /// Finds a function definition that follows or contains the given line number. /// </summary> /// <param name="scriptFile">Open script file.</param> /// <param name="lineNumber">The 1 based line on which to look for function definition.</param> /// <param name="helpLocation"></param> /// <returns>If found, returns the function definition, otherwise, returns null.</returns> public FunctionDefinitionAst GetFunctionDefinitionForHelpComment( ScriptFile scriptFile, int lineNumber, out string helpLocation) { // check if the next line contains a function definition FunctionDefinitionAst funcDefnAst = GetFunctionDefinitionAtLine(scriptFile, lineNumber + 1); if (funcDefnAst != null) { helpLocation = "before"; return(funcDefnAst); } // find all the script definitions that contain the line `lineNumber` IEnumerable <Ast> foundAsts = scriptFile.ScriptAst.FindAll( ast => { var fdAst = ast as FunctionDefinitionAst; if (fdAst == null) { return(false); } return(fdAst.Body.Extent.StartLineNumber < lineNumber && fdAst.Body.Extent.EndLineNumber > lineNumber); }, true); if (foundAsts == null || !foundAsts.Any()) { helpLocation = null; return(null); } // of all the function definitions found, return the innermost function // definition that contains `lineNumber` foreach (FunctionDefinitionAst foundAst in foundAsts.Cast <FunctionDefinitionAst>()) { if (funcDefnAst == null) { funcDefnAst = foundAst; continue; } if (funcDefnAst.Extent.StartOffset >= foundAst.Extent.StartOffset && funcDefnAst.Extent.EndOffset <= foundAst.Extent.EndOffset) { funcDefnAst = foundAst; } } // TODO use tokens to check for non empty character instead of just checking for line offset if (funcDefnAst.Body.Extent.StartLineNumber == lineNumber - 1) { helpLocation = "begin"; return(funcDefnAst); } if (funcDefnAst.Body.Extent.EndLineNumber == lineNumber + 1) { helpLocation = "end"; return(funcDefnAst); } // If we didn't find a function definition, then return null helpLocation = null; return(null); }
/// <summary> /// Adds each function defintion as a /// </summary> /// <param name="functionDefinitionAst">A functionDefinitionAst object in the script's AST</param> /// <returns>A decision to stop searching if the right symbol was found, /// or a decision to continue if it wasn't found</returns> public override AstVisitAction VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) { return(this.findSymbolsVisitor.VisitFunctionDefinition(functionDefinitionAst)); }
public async Task <CommentHelpRequestResult> Handle(CommentHelpRequestParams request, CancellationToken cancellationToken) { CommentHelpRequestResult result = new(); if (!_workspaceService.TryGetFile(request.DocumentUri, out ScriptFile scriptFile)) { return(result); } int triggerLine = request.TriggerPosition.Line + 1; FunctionDefinitionAst functionDefinitionAst = SymbolsService.GetFunctionDefinitionForHelpComment( scriptFile, triggerLine, out string helpLocation); if (functionDefinitionAst == null) { return(result); } IScriptExtent funcExtent = functionDefinitionAst.Extent; string funcText = funcExtent.Text; if (helpLocation.Equals("begin")) { // check if the previous character is `<` because it invalidates // the param block the follows it. IList <string> lines = ScriptFile.GetLinesInternal(funcText); int relativeTriggerLine0b = triggerLine - funcExtent.StartLineNumber; if (relativeTriggerLine0b > 0 && lines[relativeTriggerLine0b].IndexOf("<", StringComparison.OrdinalIgnoreCase) > -1) { lines[relativeTriggerLine0b] = string.Empty; } funcText = string.Join("\n", lines); } string helpText = await _analysisService.GetCommentHelpText(funcText, helpLocation, forBlockComment : request.BlockComment).ConfigureAwait(false); if (helpText == null) { return(result); } List <string> helpLines = ScriptFile.GetLinesInternal(helpText); if (helpLocation != null && !helpLocation.Equals("before", StringComparison.OrdinalIgnoreCase)) { // we need to trim the leading `{` and newline when helpLocation=="begin" helpLines.RemoveAt(helpLines.Count - 1); // we also need to trim the leading newline when helpLocation=="end" helpLines.RemoveAt(0); } // Trim trailing newline from help text. if (string.IsNullOrEmpty(helpLines[helpLines.Count - 1])) { helpLines.RemoveAt(helpLines.Count - 1); } result.Content = helpLines.ToArray(); return(result); }
object ICustomAstVisitor.VisitFunctionDefinition(FunctionDefinitionAst functionDefinitionAst) => ProcessRewriter(VisitFunctionDefinition, functionDefinitionAst);