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); } } }
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(); }
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); }