public ExtractMethodModel(IActiveCodePaneEditor editor, Declarations declarations, QualifiedSelection selection) { _sourceMember = declarations.FindSelectedDeclaration(selection, Declarations.ProcedureTypes, d => ((ParserRuleContext)d.Context.Parent).GetSelection()); if (_sourceMember == null) { throw new InvalidOperationException("Invalid selection."); } _extractedMethod = new ExtractedMethod(); _selection = selection; _selectedCode = editor.GetLines(selection.Selection); var inScopeDeclarations = declarations.Items.Where(item => item.ParentScope == _sourceMember.Scope).ToList(); var inSelection = inScopeDeclarations.SelectMany(item => item.References) .Where(item => selection.Selection.Contains(item.Selection)) .ToList(); var usedInSelection = new HashSet <Declaration>(inScopeDeclarations.Where(item => item.References.Any(reference => inSelection.Contains(reference)))); var usedBeforeSelection = new HashSet <Declaration>(inScopeDeclarations.Where(item => item.References.Any(reference => reference.Selection.StartLine < selection.Selection.StartLine))); var usedAfterSelection = new HashSet <Declaration>(inScopeDeclarations.Where(item => item.References.Any(reference => reference.Selection.StartLine > selection.Selection.EndLine))); // identifiers used inside selection and before selection (or if it's a parameter) are candidates for parameters: var input = inScopeDeclarations.Where(item => usedInSelection.Contains(item) && (usedBeforeSelection.Contains(item) || item.DeclarationType == DeclarationType.Parameter)).ToList(); // identifiers used inside selection and after selection are candidates for return values: var output = inScopeDeclarations.Where(item => usedInSelection.Contains(item) && usedAfterSelection.Contains(item)) .ToList(); // identifiers used only inside and/or after selection are candidates for locals: _locals = inScopeDeclarations.Where(item => item.DeclarationType != DeclarationType.Parameter && ( item.References.All(reference => inSelection.Contains(reference)) || (usedAfterSelection.Contains(item) && (!usedBeforeSelection.Contains(item))))) .ToList(); // locals that are only used in selection are candidates for being moved into the new method: _declarationsToMove = _locals.Where(item => !usedAfterSelection.Contains(item)).ToList(); _output = output.Select(declaration => new ExtractedParameter(declaration.AsTypeName, ExtractedParameter.PassedBy.ByRef, declaration.IdentifierName)); _input = input.Where(declaration => !output.Contains(declaration)) .Select(declaration => new ExtractedParameter(declaration.AsTypeName, ExtractedParameter.PassedBy.ByVal, declaration.IdentifierName)); }