public Declaration FindSelection(QualifiedSelection selection, DeclarationType[] validDeclarationTypes) { var target = Items .Where(item => !item.IsBuiltIn) .FirstOrDefault(item => item.IsSelectedDeclaration(selection) || item.References.Any(r => r.IsSelectedReference(selection))); if (target != null && validDeclarationTypes.Contains(target.DeclarationType)) { return target; } target = null; var targets = Items .Where(item => !item.IsBuiltIn && item.ComponentName == selection.QualifiedName.ComponentName && validDeclarationTypes.Contains(item.DeclarationType)); var currentSelection = new Selection(0, 0, int.MaxValue, int.MaxValue); foreach (var declaration in targets) { var activeSelection = new Selection(declaration.Context.Start.Line, declaration.Context.Start.Column, declaration.Context.Stop.Line, declaration.Context.Stop.Column); if (currentSelection.Contains(activeSelection) && activeSelection.Contains(selection.Selection)) { target = declaration; currentSelection = activeSelection; } foreach (var reference in declaration.References) { var proc = (dynamic)reference.Context.Parent; VBAParser.ArgsCallContext paramList; // This is to prevent throws when this statement fails: // (VBAParser.ArgsCallContext)proc.argsCall(); try { paramList = (VBAParser.ArgsCallContext)proc.argsCall(); } catch { continue; } if (paramList == null) { continue; } activeSelection = new Selection(paramList.Start.Line, paramList.Start.Column, paramList.Stop.Line, paramList.Stop.Column + paramList.Stop.Text.Length + 1); if (currentSelection.Contains(activeSelection) && activeSelection.Contains(selection.Selection)) { target = reference.Declaration; currentSelection = activeSelection; } } } return target; }
/// <summary> /// Returns the declaration contained in a qualified selection. /// To get the selection of a variable or field, use FindVariable(QualifiedSelection) /// </summary> /// <param name="declarations"></param> /// <param name="selection"></param> /// <param name="validDeclarationTypes"></param> /// <returns></returns> public static Declaration FindTarget(this IEnumerable<Declaration> declarations, QualifiedSelection selection, DeclarationType[] validDeclarationTypes) { var items = declarations.ToList(); var target = items .Where(item => !item.IsBuiltIn && validDeclarationTypes.Contains(item.DeclarationType)) .SingleOrDefault(item => item.IsSelected(selection) || item.References.Any(r => r.IsSelected(selection))); if (target != null) { return target; } var targets = items .Where(item => !item.IsBuiltIn && item.ComponentName == selection.QualifiedName.ComponentName && validDeclarationTypes.Contains(item.DeclarationType)); var currentSelection = new Selection(0, 0, int.MaxValue, int.MaxValue); foreach (var declaration in targets.Where(item => item.Context != null)) { var activeSelection = new Selection(declaration.Context.Start.Line, declaration.Context.Start.Column, declaration.Context.Stop.Line, declaration.Context.Stop.Column); if (currentSelection.Contains(activeSelection) && activeSelection.Contains(selection.Selection)) { target = declaration; currentSelection = activeSelection; } foreach (var reference in declaration.References) { var proc = (dynamic)reference.Context.Parent; var paramList = proc ; // This is to prevent throws when this statement fails: // (VBAParser.ArgsCallContext)proc.argsCall(); var method = ((Type) proc.GetType()).GetMethod("argsCall"); if (method != null) { try { paramList = method.Invoke(proc, null); } catch { continue; } } if (paramList == null) { continue; } activeSelection = new Selection(paramList.Start.Line, paramList.Start.Column, paramList.Stop.Line, paramList.Stop.Column + paramList.Stop.Text.Length + 1); if (currentSelection.Contains(activeSelection) && activeSelection.Contains(selection.Selection)) { target = reference.Declaration; currentSelection = activeSelection; } } } return target; }