Browse Source

Progress with editor Context actions.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@6179 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Martin Koníček 15 years ago
parent
commit
e7ab1474fc
  1. 2
      src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj
  2. 2
      src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/AddUsing.cs
  3. 25
      src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/Extensions.cs
  4. 35
      src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/FindNodesVisitor.cs
  5. 2
      src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/GenerateMember.cs
  6. 3
      src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementAbstractClass.cs
  7. 23
      src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementInterface.cs
  8. 40
      src/AddIns/Misc/SharpRefactoring/Project/Src/Extensions.cs
  9. 5
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  10. 7
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsService.cs
  11. 101
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/EditorASTProvider.cs
  12. 5
      src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/IContextActionsProvider.cs
  13. 2
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs

2
src/AddIns/Misc/SharpRefactoring/Project/SharpRefactoring.csproj

@ -71,6 +71,8 @@ @@ -71,6 +71,8 @@
<Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\ClassRefactoringSubmenuBuilder.cs" />
<Compile Include="Src\ContextActions\AddUsing.cs" />
<Compile Include="Src\ContextActions\Extensions.cs" />
<Compile Include="Src\ContextActions\FindNodesVisitor.cs" />
<Compile Include="Src\ContextActions\GenerateMember.cs" />
<Compile Include="Src\ContextActions\ImplementAbstractClass.cs" />
<Compile Include="Src\ContextActions\ImplementInterface.cs" />

2
src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/AddUsing.cs

@ -17,7 +17,7 @@ namespace SharpRefactoring.ContextActions @@ -17,7 +17,7 @@ namespace SharpRefactoring.ContextActions
/// </summary>
public class AddUsingProvider : IContextActionsProvider
{
public IEnumerable<IContextAction> GetAvailableActions(ITextEditor editor)
public IEnumerable<IContextAction> GetAvailableActions(EditorASTProvider editorAST)
{
yield break;
}

25
src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/Extensions.cs

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Konicek" email="martin.konicek@gmail.com"/>
// <version>$Revision: $</version>
// </file>
using System;
using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.Ast;
namespace SharpRefactoring.ContextActions
{
public static class Extensions
{
/// <summary>
/// Finds TypeDeclarations in AST tree.
/// </summary>
public static ReadOnlyCollection<TypeDeclaration> FindTypeDeclarations(this INode astTree)
{
var findVisitor = new FindTypeDeclarationsVisitor();
astTree.AcceptVisitor(findVisitor, null);
return findVisitor.Declarations;
}
}
}

35
src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/FindNodesVisitor.cs

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Konicek" email="martin.konicek@gmail.com"/>
// <version>$Revision: $</version>
// </file>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors;
namespace SharpRefactoring.ContextActions
{
/// <summary>
/// Finds TypeDeclarations in AST tree.
/// </summary>
public class FindTypeDeclarationsVisitor : AbstractAstVisitor
{
List<TypeDeclaration> foundDeclarations;
public ReadOnlyCollection<TypeDeclaration> Declarations { get; private set; }
public FindTypeDeclarationsVisitor()
{
this.foundDeclarations = new List<TypeDeclaration>();
this.Declarations = this.foundDeclarations.AsReadOnly();
}
public override object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data)
{
this.foundDeclarations.Add(typeDeclaration);
return base.VisitTypeDeclaration(typeDeclaration, data);
}
}
}

2
src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/GenerateMember.cs

@ -17,7 +17,7 @@ namespace SharpRefactoring.ContextActions @@ -17,7 +17,7 @@ namespace SharpRefactoring.ContextActions
/// </summary>
public class GenerateMemberProvider : IContextActionsProvider
{
public IEnumerable<IContextAction> GetAvailableActions(ITextEditor editor)
public IEnumerable<IContextAction> GetAvailableActions(EditorASTProvider editorAST)
{
yield break;
}

3
src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementAbstractClass.cs

@ -18,9 +18,8 @@ namespace SharpRefactoring.ContextActions @@ -18,9 +18,8 @@ namespace SharpRefactoring.ContextActions
/// </summary>
public class ImplementAbstractClassProvider : IContextActionsProvider
{
public IEnumerable<IContextAction> GetAvailableActions(ITextEditor editor)
public IEnumerable<IContextAction> GetAvailableActions(EditorASTProvider editorAST)
{
var currentLine = editor.Document.GetLine(editor.Caret.Line);
yield break;
}
}

23
src/AddIns/Misc/SharpRefactoring/Project/Src/ContextActions/ImplementInterface.cs

@ -7,6 +7,11 @@ @@ -7,6 +7,11 @@
using System;
using System.Collections.Generic;
using System.Windows;
using ICSharpCode.NRefactory;
using Ast = ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.AvalonEdit;
using ICSharpCode.SharpDevelop.Refactoring;
@ -18,10 +23,22 @@ namespace SharpRefactoring.ContextActions @@ -18,10 +23,22 @@ namespace SharpRefactoring.ContextActions
/// </summary>
public class ImplementInterfaceProvider : IContextActionsProvider
{
public IEnumerable<IContextAction> GetAvailableActions(ITextEditor editor)
public IEnumerable<IContextAction> GetAvailableActions(EditorASTProvider editorAST)
{
var currentLine = editor.Document.GetLine(editor.Caret.Line);
yield break;
// Using CurrentLineAST is basically OK, but when the "class" keyword is on different line than class name,
// parsing only one line never tells us that we are looking at TypeDeclaration
// Alternative solution could be to try to resolve also IdentifierExpression to see if it is class declaration.
var currentLineAST = editorAST.CurrentLineAST;
if (currentLineAST == null)
yield break;
var editor = editorAST.Editor;
foreach (var declaration in currentLineAST.FindTypeDeclarations()) {
if (declaration.Type == Ast.ClassType.Class || declaration.Type == Ast.ClassType.Struct) {
var rr = ParserService.Resolve(new ExpressionResult(declaration.Name), editor.Caret.Line, editor.Caret.Column, editor.FileName, editor.Document.Text);
}
}
}
}

40
src/AddIns/Misc/SharpRefactoring/Project/Src/Extensions.cs

@ -6,14 +6,13 @@ @@ -6,14 +6,13 @@
// </file>
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
namespace SharpRefactoring
{
/// <summary>
/// Description of Extensions.
/// </summary>
public static class Extensions
{
public static IMember GetInnermostMember(this ICompilationUnit unit, int caretLine, int caretColumn)
@ -37,5 +36,40 @@ namespace SharpRefactoring @@ -37,5 +36,40 @@ namespace SharpRefactoring
return instance.AllMembers
.SingleOrDefault(m => m.BodyRegion.IsInside(caretLine, caretColumn));
}
/// <summary>
/// Gets all interfaces that this class declares to implement, but its implementations are missing in the class body.
/// </summary>
public static List<IClass> GetInterfacesMissingImplementation(this IClass @class)
{
return null;
}
public static bool ClassImplementsClass(IClass targetClass, IClass baseClass)
{
bool requireAlternativeImplementation;
var targetClassType = targetClass.DefaultReturnType;
var baseClassType = baseClass.DefaultReturnType;
var targetClassMethods = targetClassType.GetMethods();
foreach (var m in baseClassType.GetMethods()) {
if (!CodeGenerator.InterfaceMemberAlreadyImplemented(targetClassMethods, m, out requireAlternativeImplementation)) {
return false;
}
}
var targetClassProperties = targetClassType.GetProperties();
foreach (var p in baseClassType.GetProperties()) {
if (!CodeGenerator.InterfaceMemberAlreadyImplemented(targetClassProperties, p, out requireAlternativeImplementation)) {
return false;
}
}
var targetClassEvents = targetClassType.GetEvents();
foreach (var e in baseClassType.GetEvents()) {
if (!CodeGenerator.InterfaceMemberAlreadyImplemented(targetClassEvents, e, out requireAlternativeImplementation)) {
return false;
}
}
return true;
}
}
}

5
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -89,8 +89,6 @@ @@ -89,8 +89,6 @@
<Compile Include="Src\Editor\AvalonEdit\AvalonEditSyntaxHighlighterAdapter.cs" />
<Compile Include="Src\Editor\AvalonEdit\AvalonEditTextEditorAdapter.cs" />
<Compile Include="Src\Editor\AvalonEdit\AvalonEditTextSourceAdapter.cs" />
<Compile Include="Src\Editor\AvalonEdit\ContextActionsService.cs" />
<Compile Include="Src\Editor\AvalonEdit\IContextActionsProvider.cs" />
<Compile Include="Src\Editor\AvalonEdit\IndentationStrategyAdapter.cs" />
<Compile Include="Src\Editor\AvalonEdit\ISnippetElementProvider.cs" />
<Compile Include="Src\Editor\AvalonEdit\TextContentCondition.cs" />
@ -334,6 +332,8 @@ @@ -334,6 +332,8 @@
<DependentUpon>ContextActionsHeaderedControl.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Src\Services\RefactoringService\ContextActions\ContextActionsService.cs" />
<Compile Include="Src\Services\RefactoringService\ContextActions\EditorASTProvider.cs" />
<Compile Include="Src\Services\RefactoringService\ContextActions\IContextAction.cs" />
<Compile Include="Src\Services\RefactoringService\ContextActions\ContextActionCommand.cs" />
<Compile Include="Src\Services\RefactoringService\ContextActions\ContextActionsControl.xaml.cs">
@ -343,6 +343,7 @@ @@ -343,6 +343,7 @@
<Compile Include="Src\Services\RefactoringService\ContextActions\ContextActionsViewModel.cs" />
<Compile Include="Src\Services\RefactoringService\ContextActions\ContextActionViewModel.cs" />
<Compile Include="Src\Services\RefactoringService\ContextActionsHelper.cs" />
<Compile Include="Src\Services\RefactoringService\ContextActions\IContextActionsProvider.cs" />
<Compile Include="Src\Services\RefactoringService\ExtractInterfaceOptions.cs" />
<Compile Include="Src\Services\RefactoringService\GoToClassAction.cs" />
<Compile Include="Src\Services\RefactoringService\GoToMemberAction.cs" />

7
src/Main/Base/Project/Src/Editor/AvalonEdit/ContextActionsService.cs → src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/ContextActionsService.cs

@ -7,10 +7,12 @@ @@ -7,10 +7,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Editor.AvalonEdit
namespace ICSharpCode.SharpDevelop.Refactoring
{
/// <summary>
/// Provides context actions available for current line of the editor.
@ -37,9 +39,10 @@ namespace ICSharpCode.SharpDevelop.Editor.AvalonEdit @@ -37,9 +39,10 @@ namespace ICSharpCode.SharpDevelop.Editor.AvalonEdit
/// </summary>
public IEnumerable<IContextAction> GetAvailableActions(ITextEditor editor)
{
var editorAST = new EditorASTProvider(editor);
// could run providers in parallel
foreach (var provider in this.providers) {
foreach (var action in provider.GetAvailableActions(editor)) {
foreach (var action in provider.GetAvailableActions(editorAST)) {
yield return action;
}
}

101
src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/EditorASTProvider.cs

@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Martin Konicek" email="martin.konicek@gmail.com"/>
// <version>$Revision: $</version>
// </file>
using System;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver;
using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.SharpDevelop.Refactoring
{
/// <summary>
/// Helper class for <see cref="IContextActionsProvider.GetAvailableActions"></see>.
/// Never keep long-lived references to this class
/// - the AST serves as one-time cache and does not get updated when editor text changes.
/// </summary>
public class EditorASTProvider
{
public ITextEditor Editor { get; private set; }
public SnippetParser snippetParser { get; private set; }
public NRefactoryResolver resolver { get; private set; }
public EditorASTProvider(ITextEditor editor)
{
if (editor == null)
throw new ArgumentNullException("editor");
this.Editor = editor;
this.snippetParser = GetSnippetParser(editor);
this.resolver = GetResolver(editor);
}
INode currentLineAST;
public INode CurrentLineAST
{
get
{
if (currentLineAST != null)
return currentLineAST;
if (snippetParser == null)
return null;
try {
var currentLine = Editor.Document.GetLine(Editor.Caret.Line);
return (currentLineAST = snippetParser.Parse(currentLine.Text));
}
catch {
return null;
}
}
}
INode currentMemberAST;
public INode CurrentMemberAST
{
get
{
if (resolver == null)
return null;
if (currentMemberAST != null)
return currentMemberAST;
try {
resolver.Initialize(ParserService.GetParseInformation(Editor.FileName), Editor.Caret.Line, Editor.Caret.Column);
return (currentMemberAST = resolver.ParseCurrentMember(Editor.Document.Text));
}
catch {
return null;
}
}
}
SnippetParser GetSnippetParser(ITextEditor editor)
{
var lang = GetEditorLanguage(editor);
if (lang != null) {
return new SnippetParser(lang.Value);
}
return null;
}
NRefactoryResolver GetResolver(ITextEditor editor)
{
if (editor == null || editor.Language == null)
return null;
return new NRefactoryResolver(editor.Language.Properties);
}
SupportedLanguage? GetEditorLanguage(ITextEditor editor)
{
if (editor == null || editor.Language == null)
return null;
if (editor.Language.Properties == LanguageProperties.CSharp)
return SupportedLanguage.CSharp;
if (editor.Language.Properties == LanguageProperties.VBNet)
return SupportedLanguage.VBNet;
return null;
}
}
}

5
src/Main/Base/Project/Src/Editor/AvalonEdit/IContextActionsProvider.cs → src/Main/Base/Project/Src/Services/RefactoringService/ContextActions/IContextActionsProvider.cs

@ -6,9 +6,10 @@ @@ -6,9 +6,10 @@
// </file>
using System;
using System.Collections.Generic;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Editor.AvalonEdit
namespace ICSharpCode.SharpDevelop.Refactoring
{
/// <summary>
/// Provides <see cref="ContextAction" />s to appear in a popup on the left side of the editor.
@ -18,6 +19,6 @@ namespace ICSharpCode.SharpDevelop.Editor.AvalonEdit @@ -18,6 +19,6 @@ namespace ICSharpCode.SharpDevelop.Editor.AvalonEdit
/// <summary>
/// Gets actions available for current line of the editor.
/// </summary>
IEnumerable<IContextAction> GetAvailableActions(ITextEditor editor);
IEnumerable<IContextAction> GetAvailableActions(EditorASTProvider editorAST);
}
}

2
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/CodeGenerator.cs

@ -608,7 +608,7 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -608,7 +608,7 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
return copy;
}
static bool InterfaceMemberAlreadyImplemented<T>(IEnumerable<T> existingMembers, T interfaceMember,
public static bool InterfaceMemberAlreadyImplemented<T>(IEnumerable<T> existingMembers, T interfaceMember,
out bool requireAlternativeImplementation)
where T : class, IMember
{

Loading…
Cancel
Save