Example #1
0
            public void shouldReturnAnIncrementedMethodName()
            {
                QualifiedModuleName   qualifiedModuleName;
                RubberduckParserState state;

                #region inputCode
                var inputCode = @"
Option Explicit
Private Sub Foo()
    Dim x As Integer
    x = 1 + 2
End Sub
Private Sub NewMethod
    dim a as string
    Debug.Print a
End Sub";
                #endregion inputCode

                MockParser.ParseString(inputCode, out qualifiedModuleName, out state);
                var declarations = state.AllDeclarations;

                var SUT = new ExtractedMethod();

                var expected = "NewMethod1";
                //Act
                var actual = SUT.getNewMethodName(declarations);

                //Assert
                Assert.AreEqual(expected, actual);
            }
            public void shouldConcatenateASeriesOfLines()
            {
                var notifyCalls = new List <Tuple <int, int> >();
                var codeModule  = new Mock <ICodeModuleWrapper>();

                codeModule.Setup(cm => cm.get_Lines(It.IsAny <int>(), It.IsAny <int>()))
                .Callback <int, int>((start, count) => notifyCalls.Add(Tuple.Create(start, count)));
                var selections = new List <Selection>()
                {
                    new Selection(5, 1, 5, 20), new Selection(10, 1, 12, 20)
                };
                var model  = new Mock <IExtractMethodModel>();
                var method = new ExtractedMethod();

                method.Accessibility = Accessibility.Private;
                method.Parameters    = new List <ExtractedParameter>();
                method.MethodName    = "NewMethod";
                model.Setup(m => m.RowsToRemove).Returns(selections);
                model.Setup(m => m.Method).Returns(method);

                var SUT = new ExtractMethodExtraction();

                //Act
                SUT.constructLinesOfProc(codeModule.Object, model.Object);

                //Assert
                Assert.AreEqual(Tuple.Create(5, 1), notifyCalls[0]);
                Assert.AreEqual(Tuple.Create(10, 3), notifyCalls[1]);
            }
            public void shouldReturnNewMethod()
            {
                var inputCode = @"
Option Explicit
Private Sub Foo()
    Dim x As Integer
    x = 1 + 2
End Sub";

                QualifiedModuleName qualifiedModuleName;

                using (var state = MockParser.ParseString(inputCode, out qualifiedModuleName))
                {
                    var declarations = state.AllDeclarations;

                    var SUT = new ExtractedMethod();

                    var expected = "NewMethod";
                    //Act
                    var actual = SUT.getNewMethodName(declarations);

                    //Assert

                    Assert.AreEqual(expected, actual);
                }
            }
        public ExtractMethodModel(IActiveCodePaneEditor editor, IEnumerable<Declaration> declarations, QualifiedSelection selection)
        {
            var items = declarations.ToList();

            _sourceMember = items.FindSelectedDeclaration(selection, DeclarationExtensions.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 = 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 =>
                selection.Selection.Contains(item.Selection) ||
                item.References.Any(reference => inSelection.Contains(reference))));

            var usedBeforeSelection = new HashSet<Declaration>(inScopeDeclarations.Where(item =>
                item.Selection.StartLine < selection.Selection.StartLine ||
                item.References.Any(reference => reference.Selection.StartLine < selection.Selection.StartLine)));

            var usedAfterSelection = new HashSet<Declaration>(inScopeDeclarations.Where(item =>
                item.Selection.StartLine > selection.Selection.StartLine ||
                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));
        }
        protected override void OnExecute(object parameter)
        {
            var declarations       = _state.AllDeclarations;
            var qualifiedSelection = _vbe.GetActiveSelection();

            var extractMethodValidation = new ExtractMethodSelectionValidation(declarations);
            var canExecute = extractMethodValidation.withinSingleProcedure(qualifiedSelection.Value);

            if (!canExecute)
            {
                return;
            }

            using (var pane = _vbe.ActiveCodePane)
                using (var module = pane.CodeModule)
                {
                    var extraction = new ExtractMethodExtraction();
                    // bug: access to disposed closure

                    // todo: make ExtractMethodRefactoring request reparse like everyone else.
                    var refactoring = new ExtractMethodRefactoring(module, ParseRequest, CreateMethodModel, extraction);
                    refactoring.InvalidSelection += HandleInvalidSelection;
                    refactoring.Refactor();


                    void ParseRequest(object obj) => _state.OnParseRequested(obj);

                    IExtractMethodModel CreateMethodModel(QualifiedSelection?qs, string code)
                    {
                        if (qs == null)
                        {
                            return(null);
                        }
                        //TODO: Pull these even further back;
                        //      and implement with IProvider<IExtractMethodRule>
                        var rules = new List <IExtractMethodRule>
                        {
                            new ExtractMethodRuleInSelection(),
                            new ExtractMethodRuleIsAssignedInSelection(),
                            new ExtractMethodRuleUsedAfter(),
                            new ExtractMethodRuleUsedBefore()
                        };

                        var paramClassify = new ExtractMethodParameterClassification(rules);

                        var extractedMethod      = new ExtractedMethod();
                        var extractedMethodModel = new ExtractMethodModel(extractedMethod, paramClassify);

                        extractedMethodModel.extract(declarations, qs.Value, code);
                        return(extractedMethodModel);
                    }
                }
        }
Example #6
0
        public override void Execute(object parameter)
        {
            var declarations       = _state.AllDeclarations;
            var qualifiedSelection = Vbe.ActiveCodePane.GetQualifiedSelection();

            var extractMethodValidation = new ExtractMethodSelectionValidation(declarations);
            var canExecute = extractMethodValidation.withinSingleProcedure(qualifiedSelection.Value);

            if (!canExecute)
            {
                return;
            }
            ICodeModuleWrapper codeModuleWrapper = new CodeModuleWrapper(Vbe.ActiveCodePane.CodeModule);
            VBComponent        vbComponent       = Vbe.SelectedVBComponent;

            Func <QualifiedSelection?, string, IExtractMethodModel> createMethodModel = (qs, code) =>
            {
                if (qs == null)
                {
                    return(null);
                }
                //TODO: Pull these even further back;
                //      and implement with IProvider<IExtractMethodRule>
                var rules = new List <IExtractMethodRule>()
                {
                    new ExtractMethodRuleInSelection(),
                    new ExtractMethodRuleIsAssignedInSelection(),
                    new ExtractMethodRuleUsedAfter(),
                    new ExtractMethodRuleUsedBefore()
                };

                var paramClassify = new ExtractMethodParameterClassification(rules);

                var extractedMethod      = new ExtractedMethod();
                var extractedMethodModel = new ExtractMethodModel(extractedMethod, paramClassify);
                extractedMethodModel.extract(declarations, qs.Value, code);
                return(extractedMethodModel);
            };

            var             extraction   = new ExtractMethodExtraction();
            Action <Object> parseRequest = (obj) => _state.OnParseRequested(obj, vbComponent);

            var refactoring = new ExtractMethodRefactoring(codeModuleWrapper, parseRequest, createMethodModel, extraction);

            refactoring.InvalidSelection += HandleInvalidSelection;
            refactoring.Refactor();
        }
Example #7
0
            public void shouldReturnStringCorrectly()
            {
                var method = new ExtractedMethod();

                method.Accessibility = Accessibility.Private;
                method.MethodName    = "Bar";
                method.ReturnValue   = null;
                var insertCode = "Bar x";
                var newParam   = new ExtractedParameter("Integer", ExtractedParameter.PassedBy.ByVal, "x");

                method.Parameters = new List <ExtractedParameter>()
                {
                    newParam
                };

                var actual = method.NewMethodCall();

                Debug.Print(method.NewMethodCall());

                Assert.AreEqual(insertCode, actual);
            }
            public void shouldReturnAnLeastNextMethod()
            {
                #region inputCode
                var inputCode = @"
Option Explicit
Private Sub Foo()
    Dim x As Integer
    x = 1 + 2
End Sub
Private Sub NewMethod
    dim a as string
    Debug.Print a
End Sub
Private Sub NewMethod1
    dim a as string
    Debug.Print a
End Sub
Private Sub NewMethod4
    dim a as string
    Debug.Print a
End Sub";
                #endregion inputCode

                QualifiedModuleName qualifiedModuleName;
                using (var state = MockParser.ParseString(inputCode, out qualifiedModuleName))
                {
                    var declarations = state.AllDeclarations;

                    var SUT = new ExtractedMethod();

                    var expected = "NewMethod2";
                    //Act
                    var actual = SUT.getNewMethodName(declarations);

                    //Assert
                    Assert.AreEqual(expected, actual);
                }
            }
            public void shouldInsertNewMethodAtGivenLineNoBeforeInsertingMethodCall()
            {
                var newProc    = @"
Public Sub NewMethod()
    DebugPrint ""a""
End Sub";
                var extraction = new Mock <ExtractMethodExtraction>()
                {
                    CallBase = true
                };
                IExtractMethodExtraction SUT = extraction.Object;
                var codeModule = new Mock <ICodeModuleWrapper>();
                var model      = new Mock <IExtractMethodModel>();
                var selection  = new Selection(1, 1, 1, 1);

                model.Setup(m => m.PositionForNewMethod).Returns(selection);
                var method = new ExtractedMethod();

                method.Accessibility = Accessibility.Private;
                method.Parameters    = new List <ExtractedParameter>();
                method.MethodName    = "NewMethod";
                model.Setup(m => m.Method).Returns(method);
                extraction.Setup(em => em.constructLinesOfProc(It.IsAny <ICodeModuleWrapper>(), It.IsAny <IExtractMethodModel>())).Returns(newProc);
                extraction.Setup(em => em.removeSelection(It.IsAny <ICodeModuleWrapper>(), It.IsAny <IEnumerable <Selection> >()));

                var inserted = new List <Tuple <int, string> >();

                codeModule.Setup(cm => cm.InsertLines(It.IsAny <int>(), It.IsAny <string>())).Callback <int, string>((line, data) => inserted.Add(Tuple.Create(line, data)));
                SUT.apply(codeModule.Object, model.Object, selection);

                var expected = Tuple.Create(selection.StartLine, newProc);
                var actual   = inserted[0];

                //Make sure the first insert inserted the rows.
                Assert.AreEqual(expected, actual);
            }
        public void shouldNotProduceDuplicateDimOfz()
        {
            #region inputCode
            var inputCode = @"
Option explicit
Public Sub CodeWithDeclaration()
    Dim x as long
    Dim y as long

    x = 1 + 2
    DebugPrint x                      '8
    y = x + 1
    Dim z as long
    z = x  
    DebugPrint z                      '12
    x = 2
    DebugPrint y


End Sub                                '17
Public Sub DebugPrint(byval g as long)
End Sub
                                       '20

";

            var selectedCode = @"
    DebugPrint x                      '8
    y = x + 1
    Dim z as long
    z = x  
    DebugPrint z                      '12
";
            var expectedCode = @"
Option explicit
Public Sub CodeWithDeclaration()
    Dim x as long
    Dim y as long

    x = 1 + 2
NewMethod x, y
    x = 2
    DebugPrint y


End Sub                                '17
Private Sub NewMethod(ByRef x As long, ByRef y As long) 
    Dim z as long
    DebugPrint x                      '8
    y = x + 1
    z = x  
    DebugPrint z                      '12
End Sub
Public Sub DebugPrint(byval g as long)
End Sub
                                       '20

";
            #endregion

            QualifiedModuleName   qualifiedModuleName;
            RubberduckParserState state;
            MockParser.ParseString(inputCode, out qualifiedModuleName, out state);
            var declarations = state.AllDeclarations;

            var selection = new Selection(8, 1, 12, 50);
            QualifiedSelection?qSelection = new QualifiedSelection(qualifiedModuleName, selection);

            List <IExtractMethodRule> emRules = new List <IExtractMethodRule>()
            {
                new ExtractMethodRuleInSelection(),
                new ExtractMethodRuleIsAssignedInSelection(),
                new ExtractMethodRuleUsedBefore(),
                new ExtractMethodRuleUsedAfter(),
                new ExtractMethodRuleExternalReference()
            };

            var codeModule      = new CodeModuleWrapper(qualifiedModuleName.Component.CodeModule);
            var extractedMethod = new ExtractedMethod();
            var paramClassify   = new ExtractMethodParameterClassification(emRules);
            var model           = new ExtractMethodModel(extractedMethod, paramClassify);
            model.extract(declarations, qSelection.Value, selectedCode);

            var SUT = new ExtractMethodExtraction();

            //Act
            SUT.apply(codeModule, model, selection);

            //Assert
            var actual = codeModule.get_Lines(1, 1000);
            Assert.AreEqual(expectedCode, actual);
        }