// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Collections.Generic; using System.Linq; using CSharpBinding.Parser; using ICSharpCode.AvalonEdit.Document; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp.Refactoring; using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Parser; namespace CSharpBinding.Refactoring { /// /// Refactoring change script. /// sealed class SDScript : DocumentScript { readonly ITextEditor editor; readonly TextSegmentCollection textSegmentCollection; readonly SDRefactoringContext context; public SDScript(ITextEditor editor, SDRefactoringContext context) : base(editor.Document, new CSharpFormattingOptions(), context.TextEditorOptions) { this.editor = editor; this.context = context; this.textSegmentCollection = new TextSegmentCollection((TextDocument)editor.Document); } protected override ISegment CreateTrackedSegment(int offset, int length) { var segment = new TextSegment(); segment.StartOffset = offset; segment.Length = length; textSegmentCollection.Add(segment); return segment; } public override void FormatText(AstNode node) { var parseInfo = SD.ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation; if (parseInfo != null) { //var startLocation = editor.Document.GetLocation(offset); //var endLocation = editor.Document.GetLocation(offset + length); //var node = parseInfo.CompilationUnit.GetNodeContaining(startLocation, endLocation); var formatter = new AstFormattingVisitor(new CSharpFormattingOptions(), editor.Document, context.TextEditorOptions); parseInfo.CompilationUnit.AcceptVisitor(formatter); var segment = GetSegment(node); formatter.ApplyChanges(segment.Offset, segment.Length); } else { base.FormatText(node); } } public override void Select(AstNode node) { var segment = GetSegment(node); int startOffset = segment.Offset; int endOffset = segment.EndOffset; // If the area to select includes a newline (e.g. node is a statement), // exclude that newline from the selection. if (endOffset > startOffset && editor.Document.GetLineByOffset(endOffset).Offset == endOffset) { endOffset = editor.Document.GetLineByOffset(endOffset).PreviousLine.EndOffset; } editor.Select(startOffset, endOffset - startOffset); } public override void Link(params AstNode[] nodes) { // 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() { base.Dispose(); // refresh parse information so that the issue can disappear immediately SD.ParserService.ParseAsync(editor.FileName, editor.Document).FireAndForget(); } } }