Skip to content

Commit

Permalink
Kill the extra parse in Extract Interface
Browse files Browse the repository at this point in the history
  • Loading branch information
Hosch250 committed Mar 25, 2017
1 parent d16f5db commit ae55bfd
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 150 deletions.
Expand Up @@ -8,13 +8,12 @@ namespace Rubberduck.Refactorings.ExtractInterface
{
public class ExtractInterfaceModel
{
private readonly Declaration _targetDeclaration;
public Declaration TargetDeclaration { get { return _targetDeclaration; } }
public RubberduckParserState State { get; }
public Declaration TargetDeclaration { get; }

public string InterfaceName { get; set; }

private IEnumerable<InterfaceMember> _members = new List<InterfaceMember>();
public IEnumerable<InterfaceMember> Members { get { return _members; } set { _members = value; } }
public IEnumerable<InterfaceMember> Members { get; set; } = new List<InterfaceMember>();

private static readonly DeclarationType[] ModuleTypes =
{
Expand All @@ -23,7 +22,7 @@ public class ExtractInterfaceModel
DeclarationType.UserForm
};

private static readonly DeclarationType[] MemberTypes =
public static readonly DeclarationType[] MemberTypes =
{
DeclarationType.Procedure,
DeclarationType.Function,
Expand All @@ -34,22 +33,23 @@ public class ExtractInterfaceModel

public ExtractInterfaceModel(RubberduckParserState state, QualifiedSelection selection)
{
State = state;
var declarations = state.AllDeclarations.ToList();
var candidates = declarations.Where(item => !item.IsBuiltIn && ModuleTypes.Contains(item.DeclarationType)).ToList();

_targetDeclaration = candidates.SingleOrDefault(item =>
TargetDeclaration = candidates.SingleOrDefault(item =>
item.QualifiedSelection.QualifiedName.Equals(selection.QualifiedName));

if (_targetDeclaration == null)
if (TargetDeclaration == null)
{
return;
}

InterfaceName = "I" + TargetDeclaration.IdentifierName;

_members = declarations.Where(item => !item.IsBuiltIn
&& item.ProjectId == _targetDeclaration.ProjectId
&& item.ComponentName == _targetDeclaration.ComponentName
Members = declarations.Where(item => !item.IsBuiltIn
&& item.ProjectId == TargetDeclaration.ProjectId
&& item.ComponentName == TargetDeclaration.ComponentName
&& (item.Accessibility == Accessibility.Public || item.Accessibility == Accessibility.Implicit)
&& MemberTypes.Contains(item.DeclarationType))
.OrderBy(o => o.Selection.StartLine)
Expand Down
@@ -1,12 +1,11 @@
using System;
using System.Linq;
using Rubberduck.Parsing.Grammar;
using Rubberduck.Parsing.PostProcessing;
using Rubberduck.Parsing.Symbols;
using Rubberduck.Parsing.VBA;
using Rubberduck.Refactorings.ImplementInterface;
using Rubberduck.UI;
using Rubberduck.VBEditor;
using NLog;
using Rubberduck.VBEditor.SafeComWrappers;
using Rubberduck.VBEditor.SafeComWrappers.Abstract;

Expand All @@ -15,16 +14,13 @@ namespace Rubberduck.Refactorings.ExtractInterface
public class ExtractInterfaceRefactoring : IRefactoring
{
private readonly IVBE _vbe;
private readonly RubberduckParserState _state;
private readonly IMessageBox _messageBox;
private readonly IRefactoringPresenterFactory<IExtractInterfacePresenter> _factory;
private ExtractInterfaceModel _model;
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

public ExtractInterfaceRefactoring(IVBE vbe, RubberduckParserState state, IMessageBox messageBox, IRefactoringPresenterFactory<IExtractInterfacePresenter> factory)
public ExtractInterfaceRefactoring(IVBE vbe, IMessageBox messageBox, IRefactoringPresenterFactory<IExtractInterfacePresenter> factory)
{
_vbe = vbe;
_state = state;
_messageBox = messageBox;
_factory = factory;
}
Expand All @@ -44,27 +40,27 @@ public void Refactor()
}

var pane = _vbe.ActiveCodePane;
QualifiedSelection? oldSelection;
if (!pane.IsWrappingNullReference)
{
QualifiedSelection? oldSelection;
if (!pane.IsWrappingNullReference)
var module = pane.CodeModule;
{
var module = pane.CodeModule;
{
oldSelection = module.GetQualifiedSelection();
}
}
else
{
return;
oldSelection = module.GetQualifiedSelection();
}
}
else
{
return;
}

AddInterface();
AddInterface();

if (oldSelection.HasValue)
{
pane.Selection = oldSelection.Value.Selection;
}
if (oldSelection.HasValue)
{
pane.Selection = oldSelection.Value.Selection;
}

_model.State.OnParseRequested(this);
}

public void Refactor(QualifiedSelection target)
Expand Down Expand Up @@ -95,47 +91,32 @@ public void Refactor(Declaration target)

private void AddInterface()
{
var rewriter = _model.State.GetRewriter(_model.TargetDeclaration);

var firstNonFieldMember = _model.State.DeclarationFinder.Members(_model.TargetDeclaration)
.OrderBy(o => o.Selection)
.First(m => ExtractInterfaceModel.MemberTypes.Contains(m.DeclarationType));
rewriter.InsertBefore(firstNonFieldMember.Context.Start.TokenIndex, $"Implements {_model.InterfaceName}{Environment.NewLine}{Environment.NewLine}");

AddInterfaceMembersToClass(rewriter);

var components = _model.TargetDeclaration.Project.VBComponents;
var interfaceComponent = components.Add(ComponentType.ClassModule);
var interfaceModule = interfaceComponent.CodeModule;
{
interfaceComponent.Name = _model.InterfaceName;
interfaceComponent.Name = _model.InterfaceName;

var optionPresent = interfaceModule.CountOfLines > 1;
if (!optionPresent)
{
interfaceModule.InsertLines(1, Tokens.Option + ' ' + Tokens.Explicit + Environment.NewLine);
}
interfaceModule.InsertLines(3, GetInterfaceModuleBody());

var module = _model.TargetDeclaration.QualifiedSelection.QualifiedName.Component.CodeModule;
{
_insertionLine = module.CountOfDeclarationLines + 1;
module.InsertLines(_insertionLine, Tokens.Implements + ' ' + _model.InterfaceName + Environment.NewLine);

_state.StateChanged += _state_StateChanged;
_state.OnParseRequested(this);
}
var optionPresent = interfaceModule.CountOfLines > 1;
if (!optionPresent)
{
interfaceModule.InsertLines(1, Tokens.Option + ' ' + Tokens.Explicit + Environment.NewLine);
}
interfaceModule.InsertLines(3, GetInterfaceModuleBody());
}

private int _insertionLine;
private void _state_StateChanged(object sender, EventArgs e)
private void AddInterfaceMembersToClass(IModuleRewriter rewriter)
{
if (_state.Status != ParserState.Ready)
{
return;
}

_state.StateChanged -= _state_StateChanged;
var qualifiedSelection = new QualifiedSelection(_model.TargetDeclaration.QualifiedSelection.QualifiedName, new Selection(_insertionLine, 1, _insertionLine, 1));
var pane = _vbe.ActiveCodePane;
{
pane.Selection = qualifiedSelection.Selection;
}

var implementInterfaceRefactoring = new ImplementInterfaceRefactoring(_vbe, _state, _messageBox);
implementInterfaceRefactoring.Refactor(qualifiedSelection);
var implementInterfaceRefactoring = new ImplementInterfaceRefactoring(_vbe, _model.State, _messageBox);
implementInterfaceRefactoring.Refactor(_model.Members.Where(m => m.IsSelected).Select(m => m.Member).ToList(), rewriter, _model.InterfaceName);
}

private string GetInterfaceModuleBody()
Expand Down
Expand Up @@ -21,8 +21,8 @@ public override string ToString()

public class InterfaceMember : ViewModelBase
{
private Declaration Member { get; }
private IEnumerable<Parameter> MemberParams { get; }
public Declaration Member { get; }
public IEnumerable<Parameter> MemberParams { get; }
private string Type { get; }

private string MemberType { get; set; }
Expand Down

0 comments on commit ae55bfd

Please sign in to comment.