public string FormatText (CSharpFormattingPolicy policy, TextStylePolicy textPolicy, string mimeType, string input, int startOffset, int endOffset) { var data = new TextEditorData (); data.Document.SuppressHighlightUpdate = true; data.Document.MimeType = mimeType; data.Document.FileName = "toformat.cs"; if (textPolicy != null) { data.Options.TabsToSpaces = textPolicy.TabsToSpaces; data.Options.TabSize = textPolicy.TabWidth; data.Options.IndentationSize = textPolicy.IndentWidth; data.Options.IndentStyle = textPolicy.RemoveTrailingWhitespace ? IndentStyle.Virtual : IndentStyle.Smart; } data.Text = input; // System.Console.WriteLine ("-----"); // System.Console.WriteLine (data.Text.Replace (" ", ".").Replace ("\t", "->")); // System.Console.WriteLine ("-----"); var parser = new CSharpParser (); var compilationUnit = parser.Parse (data); bool hadErrors = parser.HasErrors; if (hadErrors) { // foreach (var e in parser.ErrorReportPrinter.Errors) // Console.WriteLine (e.Message); return input.Substring (startOffset, Math.Max (0, Math.Min (endOffset, input.Length) - startOffset)); } var originalVersion = data.Document.Version; var textEditorOptions = data.CreateNRefactoryTextEditorOptions (); var formattingVisitor = new ICSharpCode.NRefactory.CSharp.CSharpFormatter ( policy.CreateOptions (), textEditorOptions ) { FormattingMode = FormattingMode.Intrusive }; var changes = formattingVisitor.AnalyzeFormatting (data.Document, compilationUnit); try { changes.ApplyChanges (startOffset, endOffset - startOffset); } catch (Exception e) { LoggingService.LogError ("Error in code formatter", e); return input.Substring (startOffset, Math.Max (0, Math.Min (endOffset, input.Length) - startOffset)); } // check if the formatter has produced errors parser = new CSharpParser (); parser.Parse (data); if (parser.HasErrors) { LoggingService.LogError ("C# formatter produced source code errors. See console for output."); return input.Substring (startOffset, Math.Max (0, Math.Min (endOffset, input.Length) - startOffset)); } var currentVersion = data.Document.Version; string result = data.GetTextBetween (startOffset, originalVersion.MoveOffsetTo (currentVersion, endOffset, ICSharpCode.NRefactory.Editor.AnchorMovementType.Default)); data.Dispose (); return result; }
public string FormatText (CSharpFormattingPolicy policy, TextStylePolicy textPolicy, string mimeType, string input, int startOffset, int endOffset) { var data = new TextEditorData (); data.Document.SuppressHighlightUpdate = true; data.Document.MimeType = mimeType; data.Document.FileName = "toformat.cs"; if (textPolicy != null) { data.Options.TabsToSpaces = textPolicy.TabsToSpaces; data.Options.TabSize = textPolicy.TabWidth; data.Options.DefaultEolMarker = textPolicy.GetEolMarker (); } data.Options.OverrideDocumentEolMarker = true; data.Text = input; // System.Console.WriteLine ("-----"); // System.Console.WriteLine (data.Text.Replace (" ", ".").Replace ("\t", "->")); // System.Console.WriteLine ("-----"); var parser = new CSharpParser (); var compilationUnit = parser.Parse (data); bool hadErrors = parser.HasErrors; if (hadErrors) { // foreach (var e in parser.ErrorReportPrinter.Errors) // Console.WriteLine (e.Message); return input.Substring (startOffset, Math.Max (0, Math.Min (endOffset, input.Length) - startOffset)); } var adapter = new TextEditorDataAdapter (data); var formattingVisitor = new ICSharpCode.NRefactory.CSharp.AstFormattingVisitor (policy.CreateOptions (), adapter, new FormattingActionFactory (data)) { HadErrors = hadErrors }; compilationUnit.AcceptVisitor (formattingVisitor, null); var changes = new List<ICSharpCode.NRefactory.CSharp.Refactoring.Action> (); changes.AddRange (formattingVisitor.Changes. Where (c => (startOffset <= c.Offset && c.Offset < endOffset))); MDRefactoringContext.MdScript.RunActions (changes, null); // check if the formatter has produced errors parser = new CSharpParser (); parser.Parse (data); if (parser.HasErrors) { LoggingService.LogError ("C# formatter produced source code errors. See console for output."); Console.WriteLine (data.Text); return input.Substring (startOffset, Math.Max (0, Math.Min (endOffset, input.Length) - startOffset)); } int end = endOffset; foreach (TextReplaceAction c in changes) { end -= c.RemovedChars; if (c.InsertedText != null) end += c.InsertedText.Length; } /* System.Console.WriteLine ("-----"); System.Console.WriteLine (data.Text.Replace (" ", "^").Replace ("\t", "->")); System.Console.WriteLine ("-----");*/ string result = data.GetTextBetween (startOffset, Math.Min (data.Length, end)); data.Dispose (); return result; }
public TemplateResult FillVariables (TemplateContext context) { var expansion = CodeTemplateService.GetExpansionObject (this); var result = new TemplateResult (); var sb = new StringBuilder (); int lastOffset = 0; string code = context.Document.Editor.FormatString (context.InsertPosition, context.TemplateCode); result.TextLinks = new List<TextLink> (); foreach (Match match in variableRegEx.Matches (code)) { string name = match.Groups [1].Value; sb.Append (code.Substring (lastOffset, match.Index - lastOffset)); lastOffset = match.Index + match.Length; if (string.IsNullOrEmpty (name)) { // $$ is interpreted as $ sb.Append ("$"); } else if (name == "end") { result.CaretEndOffset = sb.Length; } else if (name == "selected") { if (!string.IsNullOrEmpty (context.SelectedText)) { string indent = GetIndent (sb); string selection = Reindent (context.SelectedText, indent); sb.Append (selection); } } if (!variableDecarations.ContainsKey (name)) continue; TextLink link = result.TextLinks.Find (l => l.Name == name); bool isNew = link == null; if (isNew) { link = new TextLink (name); if (!string.IsNullOrEmpty (variableDecarations [name].ToolTip)) link.Tooltip = GettextCatalog.GetString (variableDecarations [name].ToolTip); link.Values = new CodeTemplateListDataProvider (variableDecarations [name].Values); if (!string.IsNullOrEmpty (variableDecarations [name].Function)) { link.Values = expansion.RunFunction (context, null, variableDecarations [name].Function); } result.TextLinks.Add (link); } link.IsEditable = variableDecarations [name].IsEditable; link.IsIdentifier = variableDecarations [name].IsIdentifier; if (!string.IsNullOrEmpty (variableDecarations [name].Function)) { IListDataProvider<string > functionResult = expansion.RunFunction (context, null, variableDecarations [name].Function); if (functionResult != null && functionResult.Count > 0) { string s = (string)functionResult [functionResult.Count - 1]; if (s == null) { if (variableDecarations.ContainsKey (name)) s = variableDecarations [name].Default; } if (s != null) { link.AddLink (new TextSegment (sb.Length, s.Length)); if (isNew) { link.GetStringFunc = delegate (Func<string, string> callback) { return expansion.RunFunction (context, callback, variableDecarations [name].Function); }; } sb.Append (s); } } else { AddDefaultValue (sb, link, name); } } else { AddDefaultValue (sb, link, name); } } sb.Append (code.Substring (lastOffset, code.Length - lastOffset)); // format & indent template code var data = new TextEditorData (); data.Text = sb.ToString (); data.Document.TextReplaced += delegate(object sender, DocumentChangeEventArgs e) { int delta = e.ChangeDelta; foreach (var link in result.TextLinks) { link.Links = new List<TextSegment> (link.Links.AdjustSegments (e)); } if (result.CaretEndOffset > e.Offset) result.CaretEndOffset += delta; }; var formatter = CodeFormatterService.GetFormatter (context.Document.Editor.Document.MimeType); if (formatter != null && context.Document.HasProject) { formatter.OnTheFlyFormat (context.Document, 0, data.Length); } IndentCode (data, context.LineIndent); result.Code = data.Text; data.Dispose (); return result; }
public static void Format (PolicyContainer policyParent, IEnumerable<string> mimeTypeChain, MonoDevelop.Ide.Gui.Document data, ProjectDom dom, DomLocation location, bool correctBlankLines, bool runAferCR = false) { if (data.ParsedDocument == null || data.ParsedDocument.CompilationUnit == null) return; var member = data.ParsedDocument.CompilationUnit.GetMemberAt (location.Line + (runAferCR ? -1 : 0), location.Column); if (member == null || member.Location.IsEmpty || member.BodyRegion.End.IsEmpty) return; StringBuilder sb = new StringBuilder (); int closingBrackets = 0; DomRegion validRegion = DomRegion.Empty; foreach (var u in data.ParsedDocument.CompilationUnit.Usings.Where (us => us.IsFromNamespace)) { // the dom parser breaks A.B.C into 3 namespaces with the same region, this is filtered here if (u.ValidRegion == validRegion) continue; validRegion = u.ValidRegion; sb.Append ("namespace Stub {"); closingBrackets++; } var parent = member.DeclaringType; while (parent != null) { sb.Append ("class Stub {"); closingBrackets++; parent = parent.DeclaringType; } sb.AppendLine (); int startOffset = sb.Length; sb.Append (data.Editor.GetTextBetween (member.Location.Line, 1, member.BodyRegion.End.Line + (runAferCR ? 1 : 0), member.BodyRegion.End.Column)); int endOffset = sb.Length; sb.AppendLine (); sb.Append (new string ('}', closingBrackets)); TextEditorData stubData = new TextEditorData () { Text = sb.ToString () }; stubData.Document.FileName = data.FileName; var compilationUnit = new MonoDevelop.CSharp.Parser.CSharpParser ().Parse (stubData); var policy = policyParent.Get<CSharpFormattingPolicy> (mimeTypeChain); var domSpacingVisitor = new AstSpacingVisitor (policy, stubData) { AutoAcceptChanges = false, }; compilationUnit.AcceptVisitor (domSpacingVisitor, null); var domIndentationVisitor = new AstIndentationVisitor (policy, stubData) { AutoAcceptChanges = false, }; domIndentationVisitor.CorrectBlankLines = correctBlankLines; compilationUnit.AcceptVisitor (domIndentationVisitor, null); var changes = new List<Change> (); changes.AddRange (domSpacingVisitor.Changes.Cast<TextReplaceChange> ().Where (c => startOffset < c.Offset && c.Offset < endOffset)); changes.AddRange (domIndentationVisitor.Changes.Cast<TextReplaceChange> ().Where (c => startOffset < c.Offset && c.Offset < endOffset)); int delta = data.Editor.LocationToOffset (member.Location.Line, 1) - startOffset; HashSet<int> lines = new HashSet<int> (); foreach (TextReplaceChange change in changes) { if (change is AstSpacingVisitor.MyTextReplaceChange) ((AstSpacingVisitor.MyTextReplaceChange)change).SetTextEditorData (data.Editor); change.Offset += delta; lines.Add (data.Editor.OffsetToLineNumber (change.Offset)); } RefactoringService.AcceptChanges (null, null, changes); foreach (int line in lines) data.Editor.Document.CommitLineUpdate (line); stubData.Dispose (); }
public override string FormatText (PolicyContainer policyParent, IEnumerable<string> mimeTypeChain, string input, int startOffset, int endOffset) { var data = new TextEditorData (); data.Document.SuppressHighlightUpdate = true; data.Document.MimeType = mimeTypeChain.First (); data.Document.FileName = "toformat.cs"; var textPolicy = policyParent.Get<TextStylePolicy> (mimeTypeChain); data.Options.TabsToSpaces = textPolicy.TabsToSpaces; data.Options.TabSize = textPolicy.TabWidth; data.Options.OverrideDocumentEolMarker = true; data.Options.DefaultEolMarker = textPolicy.GetEolMarker (); data.Text = input; // System.Console.WriteLine ("TABS:" + textPolicy.TabsToSpaces); endOffset += CorrectFormatting (data, startOffset, endOffset); /* System.Console.WriteLine ("-----"); System.Console.WriteLine (data.Text.Replace (" ", ".").Replace ("\t", "->")); System.Console.WriteLine ("-----");*/ var compilationUnit = new MonoDevelop.CSharp.Parser.CSharpParser ().Parse (data); var policy = policyParent.Get<CSharpFormattingPolicy> (mimeTypeChain); var domSpacingVisitor = new AstSpacingVisitor (policy, data) { AutoAcceptChanges = false, }; compilationUnit.AcceptVisitor (domSpacingVisitor, null); var domIndentationVisitor = new AstIndentationVisitor (policy, data) { AutoAcceptChanges = false, }; compilationUnit.AcceptVisitor (domIndentationVisitor, null); var changes = new List<Change> (); changes.AddRange (domSpacingVisitor.Changes. Concat (domIndentationVisitor.Changes). Where (c => c is TextReplaceChange && (startOffset <= ((TextReplaceChange)c).Offset && ((TextReplaceChange)c).Offset < endOffset))); RefactoringService.AcceptChanges (null, null, changes); int end = endOffset; foreach (TextReplaceChange c in changes) { end -= c.RemovedChars; if (c.InsertedText != null) end += c.InsertedText.Length; } /* System.Console.WriteLine ("-----"); System.Console.WriteLine (data.Text.Replace (" ", "^").Replace ("\t", "->")); System.Console.WriteLine ("-----");*/ string result = data.GetTextBetween (startOffset, Math.Min (data.Length, end)); data.Dispose (); return result; }
public static void Format (PolicyContainer policyParent, IEnumerable<string> mimeTypeChain, MonoDevelop.Ide.Gui.Document data, ProjectDom dom, DomLocation location, bool correctBlankLines, bool runAferCR/* = false*/) { if (data.ParsedDocument == null || data.ParsedDocument.CompilationUnit == null) return; var member = data.ParsedDocument.CompilationUnit.GetMemberAt (location.Line + (runAferCR ? -1 : 0), location.Column); if (member == null || member.Location.IsEmpty || member.BodyRegion.End.IsEmpty) return; StringBuilder sb = new StringBuilder (); int closingBrackets = 0; DomRegion validRegion = DomRegion.Empty; foreach (var u in data.ParsedDocument.CompilationUnit.Usings.Where (us => us.IsFromNamespace)) { // the dom parser breaks A.B.C into 3 namespaces with the same region, this is filtered here if (u.ValidRegion == validRegion || !u.ValidRegion.Contains (location)) continue; // indicates a parser error on namespace level. if (u.Namespaces.FirstOrDefault () == "<invalid>") continue; validRegion = u.ValidRegion; sb.Append ("namespace Stub {"); closingBrackets++; } var parent = member.DeclaringType; while (parent != null) { sb.Append ("class Stub {"); closingBrackets++; parent = parent.DeclaringType; } sb.AppendLine (); int startOffset = sb.Length; int memberStart = data.Editor.LocationToOffset (member.Location.Line, 1); int memberEnd = data.Editor.LocationToOffset (member.BodyRegion.End.Line + (runAferCR ? 1 : 0), member.BodyRegion.End.Column); if (memberEnd < 0) memberEnd = data.Editor.Length; sb.Append (data.Editor.GetTextBetween (memberStart, memberEnd)); int endOffset = sb.Length; sb.AppendLine (); sb.Append (new string ('}', closingBrackets)); TextEditorData stubData = new TextEditorData () { Text = sb.ToString () }; stubData.Document.FileName = data.FileName; var parser = new ICSharpCode.NRefactory.CSharp.CSharpParser (); var compilationUnit = parser.Parse (stubData); bool hadErrors = parser.HasErrors; var policy = policyParent.Get<CSharpFormattingPolicy> (mimeTypeChain); var adapter = new TextEditorDataAdapter (stubData); var domSpacingVisitor = new AstFormattingVisitor (policy.CreateOptions (), adapter, new FormattingActionFactory (data.Editor)) { HadErrors = hadErrors }; compilationUnit.AcceptVisitor (domSpacingVisitor, null); var changes = new List<ICSharpCode.NRefactory.CSharp.Refactoring.Action> (); changes.AddRange (domSpacingVisitor.Changes.Cast<TextReplaceAction> ().Where (c => startOffset < c.Offset && c.Offset < endOffset)); int delta = data.Editor.LocationToOffset (member.Location.Line, 1) - startOffset; HashSet<int > lines = new HashSet<int> (); foreach (TextReplaceAction change in changes) { change.Offset += delta; lines.Add (data.Editor.OffsetToLineNumber (change.Offset)); } // be sensible in documents with parser errors - only correct up to the caret position. if (hadErrors || data.ParsedDocument.Errors.Any (e => e.ErrorType == ErrorType.Error)) { var lastOffset = data.Editor.Caret.Offset; changes.RemoveAll (c => ((TextReplaceAction)c).Offset > lastOffset); } using (var undo = data.Editor.OpenUndoGroup ()) { MDRefactoringContext.MdScript.RunActions (changes, null); foreach (int line in lines) data.Editor.Document.CommitLineUpdate (line); } stubData.Dispose (); }
public static void Format (PolicyContainer policyParent, IEnumerable<string> mimeTypeChain, MonoDevelop.Ide.Gui.Document data, ProjectDom dom, DomLocation location, bool correctBlankLines, bool runAferCR = false) { var unit = data.ParsedDocument.CompilationUnit.Tag as MonoDevelop.CSharp.Ast.CompilationUnit; if (unit == null) return; AstLocation loc = new AstLocation (location.Line + (runAferCR ? -1 : 0), location.Column); AstNode member = null; foreach (AstNode node in MonoDevelop.CSharp.Ast.Utils.TreeTraversal.PreOrder (unit.Children, n => n.Parent != null && n.Parent.NodeType == NodeType.TypeDeclaration ? Enumerable.Empty<AstNode> () : n.Children)) { if (node.NodeType != NodeType.Member) continue; if (node.StartLocation < loc && loc <= node.EndLocation) { member = node; break; } } if (member == null) return; StringBuilder sb = new StringBuilder (); int closingBrackets = 0; var parent = member.Parent; while (parent != null) { if (parent.NodeType == NodeType.TypeDeclaration) { sb.Insert (0, "class Stub {"); closingBrackets++; } else if (parent is NamespaceDeclaration) { sb.Insert (0, "namespace Stub {"); closingBrackets++; } parent = parent.Parent; } sb.AppendLine (); System.Console.WriteLine ("caret offset:" + data.Editor.Caret.Offset); System.Console.WriteLine (data.Editor.Length); int startOffset = sb.Length; sb.Append (data.Editor.GetTextBetween (member.StartLocation.Line, 1, member.EndLocation.Line + (runAferCR ? 1 : 0), member.EndLocation.Column)); int endOffset = sb.Length; sb.AppendLine (); sb.Append (new string ('}', closingBrackets)); TextEditorData stubData = new TextEditorData () { Text = sb.ToString () }; stubData.Document.FileName = data.FileName; var compilationUnit = new MonoDevelop.CSharp.Parser.CSharpParser ().Parse (stubData); var policy = policyParent.Get<CSharpFormattingPolicy> (mimeTypeChain); var domSpacingVisitor = new AstSpacingVisitor (policy, stubData) { AutoAcceptChanges = false, }; compilationUnit.AcceptVisitor (domSpacingVisitor, null); var domIndentationVisitor = new AstIndentationVisitor (policy, stubData) { AutoAcceptChanges = false, }; domIndentationVisitor.CorrectBlankLines = correctBlankLines; compilationUnit.AcceptVisitor (domIndentationVisitor, null); var changes = new List<Change> (); changes.AddRange (domSpacingVisitor.Changes.Cast<TextReplaceChange> ().Where (c => startOffset < c.Offset && c.Offset < endOffset)); changes.AddRange (domIndentationVisitor.Changes.Cast<TextReplaceChange> ().Where (c => startOffset < c.Offset && c.Offset < endOffset)); int delta = data.Editor.LocationToOffset (member.StartLocation.Line, 1) - startOffset; HashSet<int> lines = new HashSet<int> (); foreach (TextReplaceChange change in changes) { if (change is AstSpacingVisitor.MyTextReplaceChange) ((AstSpacingVisitor.MyTextReplaceChange)change).SetTextEditorData (data.Editor); change.Offset += delta; lines.Add (data.Editor.OffsetToLineNumber (change.Offset)); } RefactoringService.AcceptChanges (null, null, changes); foreach (int line in lines) data.Editor.Document.CommitLineUpdate (line); stubData.Dispose (); }