/// <summary> /// Returns the children of this MethodDefinition that have the same name as the given <paramref name="use"/>, and the given type. /// This method searches only the immediate children, and not further descendants. /// If the <paramref name="use"/> occurs within this MethodDefinition, only the children that occur prior to that use will be returned. /// </summary> /// <typeparam name="T">The type of children to return.</typeparam> /// <param name="use">The use containing the name to search for.</param> /// <param name="searchDeclarations">Whether to search the child DeclarationStatements for named entities.</param> public override IEnumerable <T> GetNamedChildren <T>(NameUse use, bool searchDeclarations) { //location comparison is only valid if the use occurs within this method (or its children) var filterLocation = PrimaryLocation.Contains(use.Location); if (filterLocation) { var scopes = GetChildren().OfType <T>().Where(ns => ns.Name == use.Name && PositionComparer.CompareLocation(PrimaryLocation, use.Location) < 0); if (!searchDeclarations) { return(scopes); } //this will return the var decls in document order var decls = from declStmt in GetChildren().OfType <DeclarationStatement>() where PositionComparer.CompareLocation(declStmt.PrimaryLocation, use.Location) < 0 from decl in declStmt.GetDeclarations().OfType <T>() where decl.Name == use.Name select decl; return(scopes.Concat(decls)); } else { return(GetNamedChildren <T>(use.Name, searchDeclarations)); } }
/// <summary> /// This handles the "this" keyword, the "base" keyword (C# only), and the "super" keyword (Java only). /// It searches for the appropriate type definition depending on the context of the usage. /// </summary> /// <param name="use">The use to find the containing type for</param> /// <returns>The type(s) referred to by the keyword</returns> public static IEnumerable <TypeDefinition> GetTypeForKeyword(NameUse use) { if (use == null) { throw new ArgumentNullException("use"); } if (use.ParentStatement == null) { throw new ArgumentException("ParentStatement is null", "use"); } if (use.Name == "this") { //return the surrounding type definition return(use.ParentStatement.GetAncestorsAndSelf <TypeDefinition>().Take(1)); } if ((use.Name == "base" && use.ProgrammingLanguage == Language.CSharp) || (use.Name == "super" && use.ProgrammingLanguage == Language.Java)) { //return all the parent classes of the surrounding type definition var enclosingType = use.ParentStatement.GetAncestorsAndSelf <TypeDefinition>().FirstOrDefault(); if (enclosingType == null) { return(Enumerable.Empty <TypeDefinition>()); } else { return(enclosingType.GetParentTypes(true)); } } return(Enumerable.Empty <TypeDefinition>()); }
/// <summary> /// Returns the children of this statement that have the same name as the given <paramref name="use"/>, and the given type. /// This method searches only the immediate children, and not further descendants. /// If the <paramref name="use"/> occurs within this statement, this method will return only the children /// that occur prior to that use. /// </summary> /// <typeparam name="T">The type of children to return.</typeparam> /// <param name="use">The use containing the name to search for.</param> /// <param name="searchDeclarations">Whether to search the child DeclarationStatements for named entities.</param> public virtual IEnumerable <T> GetNamedChildren <T>(NameUse use, bool searchDeclarations) where T : INamedEntity { if (use == null) { throw new ArgumentNullException("use"); } //location comparison is only valid if the use occurs within this statement (or its children) bool filterLocation = PrimaryLocation.Contains(use.Location); if (filterLocation) { var scopes = GetChildren().OfType <T>().Where(ns => string.Equals(ns.Name, use.Name, StringComparison.Ordinal) && PositionComparer.CompareLocation(PrimaryLocation, use.Location) < 0); if (!searchDeclarations) { return(scopes); } //this will return the var decls in document order var decls = from declStmt in GetChildren().OfType <DeclarationStatement>() where PositionComparer.CompareLocation(declStmt.PrimaryLocation, use.Location) < 0 from decl in declStmt.GetDeclarations().OfType <T>() where string.Equals(decl.Name, use.Name, StringComparison.Ordinal) select decl; return(scopes.Concat(decls)); } else { return(GetNamedChildren <T>(use.Name, searchDeclarations)); } }
/// <summary> /// Returns the children of this namespace that have the same name as the given <paramref name="use"/>, and the given type. /// This method searches only the immediate children, and not further descendants. /// If this is a global namespace, and the lanugage is C or C++, then only children that occur in the same file as, and prior to, the use will be returned. /// If there are no such children, then all matching children will be returned. /// </summary> /// <typeparam name="T">The type of children to return.</typeparam> /// <param name="use">The use containing the name to search for.</param> /// <param name="searchDeclarations">Whether to search the child DeclarationStatements for named entities.</param> public override IEnumerable <T> GetNamedChildren <T>(NameUse use, bool searchDeclarations) { if (use == null) { throw new ArgumentNullException("use"); } var matches = base.GetNamedChildren <T>(use, searchDeclarations); if (IsGlobal && (ProgrammingLanguage == Language.C || ProgrammingLanguage == Language.CPlusPlus)) { Func <INamedEntity, bool> occursBeforeUse = delegate(INamedEntity match) { var matchLocs = match.GetLocations().ToList(); if (matchLocs.Count == 1 && string.Compare(matchLocs[0].SourceFileName, use.Location.SourceFileName, StringComparison.OrdinalIgnoreCase) == 0 && PositionComparer.CompareLocation(matchLocs[0], use.Location) >= 0) { //match occurs exclusively after the use, so don't include return(false); } return(true); }; return(matches.Where(m => occursBeforeUse(m))); } else { return(matches); } }
/// <summary> /// Returns the children of this statement that have the same name as the given <paramref name="use"/>, and the given type. /// This method searches only the immediate children, and not further descendants. /// The order of children within a NamedScope does not matter, so the location of the use is not taken into account. /// </summary> /// <typeparam name="T">The type of children to return.</typeparam> /// <param name="use">The use containing the name to search for.</param> /// <param name="searchDeclarations">Whether to search the child DeclarationStatements for named entities.</param> public override IEnumerable <T> GetNamedChildren <T>(NameUse use, bool searchDeclarations) { if (use == null) { throw new ArgumentNullException("use"); } return(GetNamedChildren <T>(use.Name, searchDeclarations)); }
/// <summary> /// Returns the children of this statement that have the same name as the given <paramref name="use"/>, and the given type. /// This method searches only the immediate children, and not further descendants. /// If the <paramref name="use"/> occurs within this statement, this method will return only the children /// that occur prior to that use. /// </summary> /// <typeparam name="T">The type of children to return.</typeparam> /// <param name="use">The use containing the name to search for.</param> /// <param name="searchDeclarations">Whether to search the child DeclarationStatements for named entities.</param> public override IEnumerable <T> GetNamedChildren <T>(NameUse use, bool searchDeclarations) { var matches = base.GetNamedChildren <T>(use, searchDeclarations); //check if we should filter the results if (ChildStatements.Count > 0) { var firstTryLoc = ChildStatements.First().PrimaryLocation; var lastTryLoc = ChildStatements.Last().PrimaryLocation; var tryBlockLocation = new SourceLocation(firstTryLoc.SourceFileName, firstTryLoc.StartingLineNumber, firstTryLoc.StartingColumnNumber, lastTryLoc.EndingLineNumber, lastTryLoc.EndingColumnNumber); if (this.PrimaryLocation.Contains(use.Location) && !tryBlockLocation.Contains(use.Location)) { //the use is within the overall TryStatement, but not in the try block. Don't return results from the try block return(matches.SkipWhile(m => tryBlockLocation.Contains(m.GetLocations().First()))); } } return(matches); }
/// <summary> /// Returns the children of this statement that have the same name as the given <paramref name="use"/>, and the given type. /// This method searches only the immediate children, and not further descendants. /// If the <paramref name="use"/> occurs within this statement, this method will return only the children /// that occur prior to that use. /// </summary> /// <typeparam name="T">The type of children to return.</typeparam> /// <param name="use">The use containing the name to search for.</param> /// <param name="searchDeclarations">Whether to search the child DeclarationStatements for named entities.</param> public override IEnumerable <T> GetNamedChildren <T>(NameUse use, bool searchDeclarations) { var matches = base.GetNamedChildren <T>(use, searchDeclarations); //check if we should filter the results if (ElseStatements.Count > 0) { var firstElseLoc = ElseStatements.First().PrimaryLocation; var lastElseLoc = ElseStatements.Last().PrimaryLocation; var elseLocation = new SourceLocation(firstElseLoc.SourceFileName, firstElseLoc.StartingLineNumber, firstElseLoc.StartingColumnNumber, lastElseLoc.EndingLineNumber, lastElseLoc.EndingColumnNumber); if (string.Compare(elseLocation.SourceFileName, use.Location.SourceFileName, StringComparison.OrdinalIgnoreCase) == 0 && elseLocation.Contains(use.Location)) { //the use is in the else-block, don't return results from the then-block return(matches.SkipWhile(m => PositionComparer.CompareLocation(m.GetLocations().First(), elseLocation) < 0)); } } return(matches); }
/// <summary> /// /// </summary> /// <param name="nu"></param> private void UpdateReturnInfoByNU(NameUse nu) { VariableDeclaration vdNameUse = FindFieldVarDecl(nu); if(vdNameUse != null) { GetSelfFields.Add(vdNameUse); } else { //update if assignedVar is a local variable var lVarInfo = FindLocalVarInfo(nu); if(lVarInfo != null) { foreach(var vd in lVarInfo.AssignedFields) { PropertyFields.Add(vd); } lVarInfo.IsReturned = true; ReturnedVariable = lVarInfo; //bnie-add } //update if assignedVar is a paramether var pVarInfo = FindParaVarInfo(nu); if(pVarInfo != null) { foreach(var vd in pVarInfo.AssignedFields) { PropertyFields.Add(vd); } pVarInfo.IsReturned = true; ReturnedVariable = lVarInfo; //bnie-add } } }
/// <summary> /// Find and return parameters' VariableInfo by the given NameUse /// </summary> /// <param name="vb"></param> /// <returns></returns> private VariableInfo FindParaVarInfo(NameUse vb) { if(vb == null) { return null; } var decl = vb.FindMatches().FirstOrDefault() as VariableDeclaration; if(decl != null) { foreach(var varInfo in ParametersInfo) { if(varInfo.Variable.Equals(decl)) { return varInfo; } } } return null; }
/// <summary> /// Find field varible declaration for the given variable (return null if it's a local variable) /// </summary> /// <param name="vb"></param> /// <returns></returns> private VariableDeclaration FindFieldVarDecl(NameUse vb) { if(vb == null) { return null; } var decl = vb.FindMatches().FirstOrDefault() as VariableDeclaration; if(decl != null) { //if did not find in the current list, but method is matching MethodDefinition md = decl.ParentStatement.GetAncestorsAndSelf<MethodDefinition>().FirstOrDefault(); if(md == null || !Method.Equals(md)) { return decl; } } return null; }
/// <summary> /// Returns the children of this statement that have the same name as the given <paramref name="use"/>, and the given type. /// This method searches only the immediate children, and not further descendants. /// If the <paramref name="use"/> occurs within this statement, this method will return only the children /// that occur prior to that use. /// </summary> /// <typeparam name="T">The type of children to return.</typeparam> /// <param name="use">The use containing the name to search for.</param> public IEnumerable <T> GetNamedChildren <T>(NameUse use) where T : INamedEntity { bool searchDeclarations = typeof(T).IsInterface || typeof(T).IsSubclassOf(typeof(Expression)); return(GetNamedChildren <T>(use, searchDeclarations)); }
/// <summary> /// Returns the children of this statement that have the same name as the given <paramref name="use"/>. /// This method searches only the immediate children, and not further descendants. /// If the <paramref name="use"/> occurs within this statement, this method will return only the children /// that occur prior to that use. /// </summary> /// <param name="use">The use containing the name to search for.</param> public IEnumerable <INamedEntity> GetNamedChildren(NameUse use) { return(GetNamedChildren <INamedEntity>(use, true)); }