Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Refactoring/DocumentScript.cs @ 13397

Last change on this file since 13397 was 11700, checked in by jkarder, 9 years ago

#2077: created branch and added first version

File size: 5.9 KB
Line 
1// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
2//
3// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4// software and associated documentation files (the "Software"), to deal in the Software
5// without restriction, including without limitation the rights to use, copy, modify, merge,
6// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7// to whom the Software is furnished to do so, subject to the following conditions:
8//
9// The above copyright notice and this permission notice shall be included in all copies or
10// substantial portions of the Software.
11//
12// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17// DEALINGS IN THE SOFTWARE.
18
19using System;
20using System.Linq;
21using System.Diagnostics;
22using ICSharpCode.NRefactory.Editor;
23using System.Collections.Generic;
24
25namespace ICSharpCode.NRefactory.CSharp.Refactoring
26{
27  /// <summary>
28  /// Script implementation based on IDocument.
29  /// </summary>
30  public class DocumentScript : Script
31  {
32    readonly IDocument currentDocument;
33   
34    public IDocument CurrentDocument {
35      get { return currentDocument; }
36    }
37    readonly IDocument originalDocument;
38   
39    public IDocument OriginalDocument {
40      get { return originalDocument; }
41    }
42    readonly IDisposable undoGroup;
43   
44   
45    public DocumentScript(IDocument document, CSharpFormattingOptions formattingOptions, TextEditorOptions options) : base(formattingOptions, options)
46    {
47      this.originalDocument = document.CreateDocumentSnapshot();
48      this.currentDocument = document;
49      Debug.Assert(currentDocument.Version.CompareAge(originalDocument.Version) == 0);
50      this.undoGroup = document.OpenUndoGroup();
51    }
52   
53    public override void Dispose()
54    {
55      // Since base.Dispose() reformats some nodes; we need to include it in the undo group
56      base.Dispose();
57      if (undoGroup != null)
58        undoGroup.Dispose();
59    }
60   
61    public override void Remove(AstNode node, bool removeEmptyLine = true)
62    {
63      var segment = GetSegment (node);
64      int startOffset = segment.Offset;
65      int endOffset = segment.EndOffset;
66      var startLine = currentDocument.GetLineByOffset (startOffset);
67      var endLine = currentDocument.GetLineByOffset (endOffset);
68     
69      if (startLine != null && endLine != null) {
70        bool removeStart = string.IsNullOrWhiteSpace (currentDocument.GetText (startLine.Offset, startOffset - startLine.Offset));
71        if (removeStart)
72          startOffset = startLine.Offset;
73        bool removeEnd = string.IsNullOrWhiteSpace (currentDocument.GetText (endOffset, endLine.EndOffset - endOffset));
74        if (removeEnd)
75          endOffset = endLine.EndOffset;
76       
77        // Remove delimiter if the whole line get's removed.
78        if (removeStart && removeEnd)
79          endOffset += endLine.DelimiterLength;
80      }
81     
82      Replace (startOffset, endOffset - startOffset, string.Empty);
83    }
84   
85    public override void Replace(int offset, int length, string newText)
86    {
87      currentDocument.Replace(offset, length, newText);
88    }
89   
90    public override int GetCurrentOffset(TextLocation originalDocumentLocation)
91    {
92      int offset = originalDocument.GetOffset(originalDocumentLocation);
93      return GetCurrentOffset(offset);
94    }
95   
96    public override int GetCurrentOffset(int originalDocumentOffset)
97    {
98      return originalDocument.Version.MoveOffsetTo(currentDocument.Version, originalDocumentOffset);
99    }
100   
101    public override void FormatText(IEnumerable<AstNode> nodes)
102    {
103      var syntaxTree = SyntaxTree.Parse(currentDocument, "dummy.cs");
104      var formatter = new CSharpFormatter(FormattingOptions, Options);
105      var segments = new List<ISegment>();
106      foreach (var node in nodes.OrderByDescending (n => n.StartLocation)) {
107        var segment = GetSegment(node);
108       
109        formatter.AddFormattingRegion (new ICSharpCode.NRefactory.TypeSystem.DomRegion (
110          currentDocument.GetLocation (segment.Offset),
111          currentDocument.GetLocation (segment.EndOffset)
112          ));
113        segments.Add(segment);
114      }
115      if (segments.Count == 0)
116        return;
117      var changes = formatter.AnalyzeFormatting (currentDocument, syntaxTree);
118      foreach (var segment in segments) {
119        changes.ApplyChanges(segment.Offset, segment.Length - 1);
120      }
121    }
122   
123    protected override int GetIndentLevelAt(int offset)
124    {
125      var line = currentDocument.GetLineByOffset(offset);
126      int spaces = 0;
127      int indentationLevel = 0;
128      for (int i = line.Offset; i < currentDocument.TextLength; i++) {
129        char c = currentDocument.GetCharAt(i);
130        if (c == '\t') {
131          spaces = 0;
132          indentationLevel++;
133        } else if (c == ' ') {
134          spaces++;
135          if (spaces == 4) {
136            spaces = 0;
137            indentationLevel++;
138          }
139        } else {
140          break;
141        }
142      }
143      return indentationLevel;
144    }
145   
146    protected override ISegment CreateTrackedSegment(int offset, int length)
147    {
148      return new TrackedSegment(this, offset, offset + length);
149    }
150   
151    sealed class TrackedSegment : ISegment
152    {
153      readonly DocumentScript script;
154      readonly ITextSourceVersion originalVersion;
155      readonly int originalStart;
156      readonly int originalEnd;
157     
158      public TrackedSegment(DocumentScript script, int originalStart, int originalEnd)
159      {
160        this.script = script;
161        this.originalVersion = script.currentDocument.Version;
162        this.originalStart = originalStart;
163        this.originalEnd = originalEnd;
164      }
165     
166      public int Offset {
167        get { return originalVersion.MoveOffsetTo(script.currentDocument.Version, originalStart); }
168      }
169     
170      public int Length {
171        get { return this.EndOffset - this.Offset; }
172      }
173     
174      public int EndOffset {
175        get { return originalVersion.MoveOffsetTo(script.currentDocument.Version, originalEnd); }
176      }
177    }
178  }
179}
Note: See TracBrowser for help on using the repository browser.