Browse Source

Add InsertWithCursor implementation.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
6e9190b6a9
  1. 4
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin
  2. 1
      src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj
  3. 237
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertionPoint.cs
  4. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs
  5. 32
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs
  6. 10
      src/Main/Base/Project/Src/Services/RefactoringService/TypeName.cs

4
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin

@ -173,10 +173,10 @@
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateDelegateAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateDelegateAction" />
<CSharpCodeActionProvider id = "CreateEventInvocator" <CSharpCodeActionProvider id = "CreateEventInvocator"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateEventInvocatorAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateEventInvocatorAction" />
<CSharpCodeActionProvider id = "CreateField"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateFieldAction" />
<CSharpCodeActionProvider id = "CreateLocalVariable" <CSharpCodeActionProvider id = "CreateLocalVariable"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateLocalVariableAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateLocalVariableAction" />
<CSharpCodeActionProvider id = "CreateField"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateFieldAction" />
<CSharpCodeActionProvider id = "CreateMethodDeclaration" <CSharpCodeActionProvider id = "CreateMethodDeclaration"
class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateMethodDeclarationAction" /> class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateMethodDeclarationAction" />
<CSharpCodeActionProvider id = "CreateProperty" <CSharpCodeActionProvider id = "CreateProperty"

1
src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

@ -66,6 +66,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Configuration\AssemblyInfo.cs" /> <Compile Include="Configuration\AssemblyInfo.cs" />
<Compile Include="Src\Refactoring\InsertionPoint.cs" />
<Compile Include="Src\Refactoring\IssueOptions.xaml.cs"> <Compile Include="Src\Refactoring\IssueOptions.xaml.cs">
<DependentUpon>IssueOptions.xaml</DependentUpon> <DependentUpon>IssueOptions.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>

237
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/InsertionPoint.cs

@ -0,0 +1,237 @@
//
// InsertionPoint.cs
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
// Copyright (c) 2010 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor;
namespace CSharpBinding.Refactoring
{
public enum NewLineInsertion
{
None,
Eol,
BlankLine
}
public class InsertionPoint
{
public TextLocation Location {
get;
set;
}
public NewLineInsertion LineBefore { get; set; }
public NewLineInsertion LineAfter { get; set; }
public InsertionPoint (TextLocation location, NewLineInsertion lineBefore, NewLineInsertion lineAfter)
{
this.Location = location;
this.LineBefore = lineBefore;
this.LineAfter = lineAfter;
}
public override string ToString ()
{
return string.Format ("[InsertionPoint: Location={0}, LineBefore={1}, LineAfter={2}]", Location, LineBefore, LineAfter);
}
void InsertNewLine (IDocument document, NewLineInsertion insertion, ref int offset)
{
string eolMarker = DocumentUtilitites.GetLineTerminator(document, 1);
string str = null;
switch (insertion) {
case NewLineInsertion.Eol:
str = eolMarker;
break;
case NewLineInsertion.BlankLine:
str = eolMarker + eolMarker;
break;
default:
return;
}
document.Insert (offset, str);
offset += str.Length;
}
public void Insert (IDocument document, string text)
{
int offset = document.GetOffset (Location);
using (var undo = document.OpenUndoGroup ()) {
text = DocumentUtilitites.NormalizeNewLines(text, document, Location.Line);
var line = document.GetLineByOffset (offset);
int insertionOffset = line.Offset + Location.Column - 1;
offset = insertionOffset;
InsertNewLine (document, LineBefore, ref offset);
document.Insert (offset, text);
offset += text.Length;
InsertNewLine (document, LineAfter, ref offset);
}
}
public static List<InsertionPoint> GetInsertionPoints (IDocument document, IUnresolvedTypeDefinition type)
{
if (type == null)
throw new ArgumentNullException ("type");
// update type from parsed document, since this is always newer.
//type = parsedDocument.GetInnermostTypeDefinition (type.GetLocation ()) ?? type;
List<InsertionPoint > result = new List<InsertionPoint> ();
int offset = document.GetOffset (type.Region.Begin);
if (offset < 0)
return result;
while (offset < document.TextLength && document.GetCharAt (offset) != '{') {
offset++;
}
var realStartLocation = document.GetLocation (offset);
result.Add (GetInsertionPosition (document, realStartLocation.Line, realStartLocation.Column));
result [0].LineBefore = NewLineInsertion.None;
foreach (var member in type.Members) {
TextLocation domLocation = member.BodyRegion.End;
if (domLocation.Line <= 0) {
domLocation = member.Region.End;
}
result.Add (GetInsertionPosition (document, domLocation.Line, domLocation.Column));
}
result [result.Count - 1].LineAfter = NewLineInsertion.None;
CheckStartPoint (document, result [0], result.Count == 1);
if (result.Count > 1) {
result.RemoveAt (result.Count - 1);
NewLineInsertion insertLine;
var lineBefore = GetLineOrNull(document, type.BodyRegion.EndLine - 1);
if (lineBefore != null && lineBefore.Length == GetLineIndent(document, lineBefore).Length) {
insertLine = NewLineInsertion.None;
} else {
insertLine = NewLineInsertion.Eol;
}
// search for line start
var line = document.GetLineByNumber (type.BodyRegion.EndLine);
int col = type.BodyRegion.EndColumn - 1;
while (col > 1 && char.IsWhiteSpace (document.GetCharAt (line.Offset + col - 2)))
col--;
result.Add (new InsertionPoint (new TextLocation (type.BodyRegion.EndLine, col), insertLine, NewLineInsertion.Eol));
CheckEndPoint (document, result [result.Count - 1], result.Count == 1);
}
/*foreach (var region in parsedDocument.UserRegions.Where (r => type.BodyRegion.IsInside (r.Region.Begin))) {
result.Add (new InsertionPoint (new DocumentLocation (region.Region.BeginLine + 1, 1), NewLineInsertion.Eol, NewLineInsertion.Eol));
result.Add (new InsertionPoint (new DocumentLocation (region.Region.EndLine, 1), NewLineInsertion.Eol, NewLineInsertion.Eol));
result.Add (new InsertionPoint (new DocumentLocation (region.Region.EndLine + 1, 1), NewLineInsertion.Eol, NewLineInsertion.Eol));
}*/
result.Sort ((left, right) => left.Location.CompareTo (right.Location));
return result;
}
static void CheckEndPoint (IDocument doc, InsertionPoint point, bool isStartPoint)
{
var line = GetLineOrNull(doc, point.Location.Line);
if (line == null)
return;
if (GetLineIndent (doc, line).Length + 1 < point.Location.Column)
point.LineBefore = NewLineInsertion.BlankLine;
if (point.Location.Column < line.Length + 1)
point.LineAfter = NewLineInsertion.Eol;
}
static void CheckStartPoint (IDocument doc, InsertionPoint point, bool isEndPoint)
{
var line = GetLineOrNull(doc, point.Location.Line);
if (line == null)
return;
if (GetLineIndent (doc, line).Length + 1 == point.Location.Column) {
int lineNr = point.Location.Line;
while (lineNr > 1 && GetLineIndent(doc, lineNr - 1).Length == doc.GetLineByNumber (lineNr - 1).Length) {
lineNr--;
}
line = GetLineOrNull(doc, lineNr);
point.Location = new TextLocation (lineNr, GetLineIndent (doc, line).Length + 1);
}
if (GetLineIndent (doc, line).Length + 1 < point.Location.Column)
point.LineBefore = NewLineInsertion.Eol;
if (point.Location.Column < line.Length + 1)
point.LineAfter = isEndPoint ? NewLineInsertion.Eol : NewLineInsertion.BlankLine;
}
static string GetLineIndent(IDocument doc, int lineNumber)
{
return GetLineIndent(doc, GetLineOrNull(doc, lineNumber));
}
static string GetLineIndent(IDocument doc, IDocumentLine line)
{
if (line == null)
return string.Empty;
else
return DocumentUtilitites.GetWhitespaceAfter(doc, line.Offset);
}
static InsertionPoint GetInsertionPosition (IDocument doc, int line, int column)
{
int bodyEndOffset = doc.GetOffset (line, column) + 1;
var curLine = GetLineOrNull(doc, line);
if (curLine != null) {
if (bodyEndOffset < curLine.EndOffset) {
// case1: positition is somewhere inside the start line
return new InsertionPoint (new TextLocation (line, column + 1), NewLineInsertion.Eol, NewLineInsertion.BlankLine);
}
}
// -> if position is at line end check next line
var nextLine = GetLineOrNull (doc, line + 1);
if (nextLine == null) // check for 1 line case.
return new InsertionPoint (new TextLocation (line, column + 1), NewLineInsertion.BlankLine, NewLineInsertion.BlankLine);
for (int i = nextLine.Offset; i < nextLine.EndOffset; i++) {
char ch = doc.GetCharAt (i);
if (!char.IsWhiteSpace (ch)) {
// case2: next line contains non ws chars.
return new InsertionPoint (new TextLocation (line + 1, 1), NewLineInsertion.Eol, NewLineInsertion.BlankLine);
}
}
// case3: whitespace line
return new InsertionPoint (new TextLocation (line + 1, 1), NewLineInsertion.Eol, NewLineInsertion.None);
}
static IDocumentLine GetLineOrNull(IDocument doc, int lineNumber)
{
if (lineNumber >= 1 && lineNumber <= doc.LineCount)
return doc.GetLineByNumber(lineNumber);
else
return null;
}
}
}

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDRefactoringContext.cs

@ -59,7 +59,7 @@ namespace CSharpBinding.Refactoring
{ {
if (editor == null) if (editor == null)
throw new InvalidOperationException("Cannot start a script in IsAvailable()."); throw new InvalidOperationException("Cannot start a script in IsAvailable().");
return new SDScript(editor, this.TextEditorOptions); return new SDScript(editor, this);
} }
public override TextLocation Location { public override TextLocation Location {

32
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using CSharpBinding.Parser; using CSharpBinding.Parser;
using ICSharpCode.AvalonEdit.Document; using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
@ -23,10 +24,12 @@ namespace CSharpBinding.Refactoring
{ {
readonly ITextEditor editor; readonly ITextEditor editor;
readonly TextSegmentCollection<TextSegment> textSegmentCollection; readonly TextSegmentCollection<TextSegment> textSegmentCollection;
readonly SDRefactoringContext context;
public SDScript(ITextEditor editor, TextEditorOptions options) : base(editor.Document, new CSharpFormattingOptions(), options) public SDScript(ITextEditor editor, SDRefactoringContext context) : base(editor.Document, new CSharpFormattingOptions(), context.TextEditorOptions)
{ {
this.editor = editor; this.editor = editor;
this.context = context;
this.textSegmentCollection = new TextSegmentCollection<TextSegment>((TextDocument)editor.Document); this.textSegmentCollection = new TextSegmentCollection<TextSegment>((TextDocument)editor.Document);
} }
@ -46,8 +49,7 @@ namespace CSharpBinding.Refactoring
//var startLocation = editor.Document.GetLocation(offset); //var startLocation = editor.Document.GetLocation(offset);
//var endLocation = editor.Document.GetLocation(offset + length); //var endLocation = editor.Document.GetLocation(offset + length);
//var node = parseInfo.CompilationUnit.GetNodeContaining(startLocation, endLocation); //var node = parseInfo.CompilationUnit.GetNodeContaining(startLocation, endLocation);
// TODO: pass TextEditorOptions var formatter = new AstFormattingVisitor(new CSharpFormattingOptions(), editor.Document, context.TextEditorOptions);
var formatter = new AstFormattingVisitor(new CSharpFormattingOptions(), editor.Document);
parseInfo.CompilationUnit.AcceptVisitor(formatter); parseInfo.CompilationUnit.AcceptVisitor(formatter);
var segment = GetSegment(node); var segment = GetSegment(node);
formatter.ApplyChanges(segment.Offset, segment.Length); formatter.ApplyChanges(segment.Offset, segment.Length);
@ -74,6 +76,30 @@ namespace CSharpBinding.Refactoring
// TODO // TODO
} }
public override void InsertWithCursor(string operation, AstNode node, InsertPosition defaultPosition)
{
AstNode contextNode = context.GetNode();
if (contextNode == null)
return;
var resolver = context.GetResolverStateBefore(contextNode);
InsertWithCursor(operation, node, resolver.CurrentTypeDefinition);
}
public override void InsertWithCursor(string operation, AstNode node, ITypeDefinition parentType)
{
if (parentType == null)
return;
var currentPart = parentType.Parts.FirstOrDefault(p => p.ParsedFile != null && string.Equals(p.ParsedFile.FileName, editor.FileName, StringComparison.OrdinalIgnoreCase));
if (currentPart != null) {
var insertionPoints = InsertionPoint.GetInsertionPoints(editor.Document, currentPart);
if (insertionPoints.Count > 0) {
int indentLevel = GetIndentLevelAt(editor.Document.GetOffset(insertionPoints[0].Location));
var output = OutputNode(indentLevel, node);
insertionPoints[0].Insert(editor.Document, output.Text);
}
}
}
public override void Dispose() public override void Dispose()
{ {
base.Dispose(); base.Dispose();

10
src/Main/Base/Project/Src/Services/RefactoringService/TypeName.cs

@ -19,12 +19,14 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public readonly string AssemblyName; public readonly string AssemblyName;
public readonly string Namespace; public readonly string Namespace;
public readonly string Name; public readonly string Name;
public readonly int TypeParameterCount;
public TypeName(string assemblyName, string @namespace, string name) public TypeName(string assemblyName, string @namespace, string name, int typeParameterCount)
{ {
this.AssemblyName = assemblyName; this.AssemblyName = assemblyName;
this.Namespace = @namespace; this.Namespace = @namespace;
this.Name = name; this.Name = name;
this.TypeParameterCount = typeParameterCount;
} }
public TypeName(ITypeDefinition typeDefinition) public TypeName(ITypeDefinition typeDefinition)
@ -35,6 +37,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
for (ITypeDefinition parent = typeDefinition.DeclaringTypeDefinition; parent != null; parent = parent.DeclaringTypeDefinition) { for (ITypeDefinition parent = typeDefinition.DeclaringTypeDefinition; parent != null; parent = parent.DeclaringTypeDefinition) {
this.Name = parent.Name + "." + this.Name; this.Name = parent.Name + "." + this.Name;
} }
this.TypeParameterCount = typeDefinition.TypeParameterCount;
} }
public override string ToString() public override string ToString()
@ -44,6 +47,8 @@ namespace ICSharpCode.SharpDevelop.Refactoring
fullName = Name; fullName = Name;
else else
fullName = Namespace + "." + Name; fullName = Namespace + "." + Name;
if (TypeParameterCount > 0)
fullName = fullName + "`" + TypeParameterCount.ToString();
if (string.IsNullOrEmpty(AssemblyName)) if (string.IsNullOrEmpty(AssemblyName))
return fullName; return fullName;
else else
@ -57,7 +62,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public bool Equals(TypeName other) public bool Equals(TypeName other)
{ {
return this.AssemblyName == other.AssemblyName && this.Namespace == other.Namespace && this.Name == other.Name; return this.AssemblyName == other.AssemblyName && this.Namespace == other.Namespace && this.Name == other.Name && this.TypeParameterCount == other.TypeParameterCount;
} }
public override int GetHashCode() public override int GetHashCode()
@ -70,6 +75,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
hashCode += 1000000009 * Namespace.GetHashCode(); hashCode += 1000000009 * Namespace.GetHashCode();
if (Name != null) if (Name != null)
hashCode += 1000000021 * Name.GetHashCode(); hashCode += 1000000021 * Name.GetHashCode();
hashCode += TypeParameterCount;
} }
return hashCode; return hashCode;
} }

Loading…
Cancel
Save