Exemplo n.º 1
0
        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));
        }