public bool Analyze (RefactoringOptions options) { var data = options.GetTextEditorData (); if (data.Document.MimeType != CSharpFormatter.MimeType) return false; var parser = new CSharpParser (); var unit = parser.Parse (data); if (unit == null) return false; resolvePosition = new DomLocation (data.Caret.Line, data.Caret.Column); if (!AnalyzeTargetExpression (options, unit)) return false; invocation = GetInvocation (unit, data); if (invocation != null) return AnalyzeInvocation (options); delegateType = GetDelegateType (options, unit); return delegateType != null; }
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; 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 MonoDevelop.CSharp.Parser.CSharpParser (); bool hadErrors = parser.ErrorReportPrinter.ErrorsCount + parser.ErrorReportPrinter.FatalCounter > 0; var compilationUnit = parser.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, HadErrors = hadErrors }; 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)); } // be sensible in documents with parser errors - only correct up to the caret position. if (parser.ErrorReportPrinter.Errors.Any (e => e.ErrorType == ErrorType.Error) || data.ParsedDocument.Errors.Any (e => e.ErrorType == ErrorType.Error)) { var lastOffset = data.Editor.Caret.Offset; changes.RemoveAll (c => ((TextReplaceChange)c).Offset > lastOffset); } RefactoringService.AcceptChanges (null, null, changes); foreach (int line in lines) data.Editor.Document.CommitLineUpdate (line); stubData.Dispose (); }
bool Analyze (RefactoringOptions options, ExtractMethodParameters param, bool fillParameter) { var data = options.GetTextEditorData (); var parser = new CSharpParser (); var unit = parser.Parse (data); var resolver = options.GetResolver (); if (unit == null) return false; var selectionRange = data.SelectionRange; var startOffset = selectionRange.Offset; while (startOffset + 1 < data.Length && char.IsWhiteSpace (data.GetCharAt (startOffset + 1))) startOffset++; var endOffset = selectionRange.EndOffset; while (startOffset < endOffset && endOffset - 1 > 0 && char.IsWhiteSpace (data.GetCharAt (endOffset - 1))) endOffset--; if (startOffset >= endOffset) return false; var endLocation = data.OffsetToLocation (endOffset); var startLocation = data.OffsetToLocation (startOffset); param.StartOffset = startOffset; param.EndOffset = endOffset; param.Nodes = new List<AstNode> (unit.GetNodesBetween (startLocation.Line, startLocation.Column, endLocation.Line, endLocation.Column)); string text = options.Document.Editor.GetTextBetween (startLocation, endLocation); param.Text = RemoveIndent (text, GetIndent (data.GetTextBetween (data.GetLine (startLocation.Line).Offset, data.GetLine (endLocation.Line).EndOffset))).TrimEnd ('\n', '\r'); VariableLookupVisitor visitor = new VariableLookupVisitor (resolver, param.Location); visitor.MemberLocation = param.DeclaringMember.Location; visitor.CutRegion = new DomRegion (startLocation.Line, startLocation.Column, endLocation.Line, endLocation.Column); if (fillParameter) { unit.AcceptVisitor (visitor, null); if (param.Nodes != null && (param.Nodes.Count == 1 && param.Nodes [0].NodeType == NodeType.Expression)) { ResolveResult resolveResult = resolver.Resolve (new ExpressionResult ("(" + text + ")"), param.Location); if (resolveResult != null && resolveResult.ResolvedType != null) param.ExpressionType = resolveResult.ResolvedType; } foreach (VariableDescriptor varDescr in visitor.VariableList.Where (v => !v.IsDefinedInsideCutRegion && (v.UsedInCutRegion || v.IsChangedInsideCutRegion || v.UsedAfterCutRegion && v.IsDefinedInsideCutRegion))) { param.Parameters.Add (varDescr); } param.Variables = new List<VariableDescriptor> (visitor.Variables.Values); param.ReferencesMember = visitor.ReferencesMember; param.OneChangedVariable = param.Variables.Count (p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion) == 1; if (param.OneChangedVariable) param.ExpressionType = param.Variables.First (p => p.IsDefinedInsideCutRegion && p.UsedAfterCutRegion).ReturnType; /* foreach (VariableDescriptor varDescr in visitor.VariableList.Where (v => !v.IsDefined && param.Variables.Contains (v))) { if (param.Parameters.Contains (varDescr)) continue; if (startLocation <= varDescr.Location && varDescr.Location < endLocation) continue; param.Parameters.Add (varDescr); } param.ChangedVariables = new HashSet<string> (visitor.Variables.Values.Where (v => v.GetsChanged).Select (v => v.Name)); */ // analyze the variables outside of the selected text IMember member = param.DeclaringMember; int bodyStartOffset = data.Document.LocationToOffset (member.BodyRegion.Start.Line, member.BodyRegion.Start.Column); int bodyEndOffset = data.Document.LocationToOffset (member.BodyRegion.End.Line, member.BodyRegion.End.Column); if (startOffset < bodyStartOffset || bodyEndOffset < endOffset) return false; text = data.Document.GetTextBetween (bodyStartOffset, startOffset) + data.Document.GetTextBetween (endOffset, bodyEndOffset); // ICSharpCode.NRefactory.Ast.INode parsedNode = provider.ParseText (text); // visitor = new VariableLookupVisitor (resolver, param.Location); // visitor.CutRegion = new DomRegion (data.MainSelection.MinLine, data.MainSelection.MaxLine); // visitor.MemberLocation = new Location (param.DeclaringMember.Location.Column, param.DeclaringMember.Location.Line); // if (parsedNode != null) // parsedNode.AcceptVisitor (visitor, null); /* param.VariablesOutside = new Dictionary<string, VariableDescriptor> (); foreach (var pair in visitor.Variables) { if (startLocation < pair.Value.Location || endLocation >= pair.Value.Location) { param.VariablesOutside.Add (pair.Key, pair.Value); } } param.OutsideVariableList = new List<VariableDescriptor> (); foreach (var v in visitor.VariableList) { if (startLocation < v.Location || endLocation >= v.Location) param.OutsideVariableList.Add (v); } param.ChangedVariablesUsedOutside = new List<VariableDescriptor> (param.Variables.Where (v => v.GetsChanged && param.VariablesOutside.ContainsKey (v.Name))); param.OneChangedVariable = param.Nodes.Count == 1 && param.Nodes[0] is BlockStatement; if (param.OneChangedVariable) param.OneChangedVariable = param.ChangedVariablesUsedOutside.Count == 1; param.VariablesToGenerate = new List<VariableDescriptor> (param.ChangedVariablesUsedOutside.Where (v => v.IsDefined)); foreach (VariableDescriptor var in param.VariablesToGenerate) { param.Parameters.Add (var); } if (param.OneChangedVariable) { param.VariablesToDefine = new List<VariableDescriptor> (param.Parameters.Where (var => !var.InitialValueUsed)); param.VariablesToDefine.ForEach (var => param.Parameters.Remove (var)); } else { param.VariablesToDefine = new List<VariableDescriptor> (); }*/ } return true; }
public void TestIfForcementWithComment () { TextEditorData data = new TextEditorData (); data.Document.FileName = "a.cs"; data.Document.Text = @"class Test { void TestMethod () { if (true) // TestComment Call (); } }"; CSharpFormattingPolicy policy = new CSharpFormattingPolicy (); policy.StatementBraceStyle = BraceStyle.EndOfLine; policy.IfElseBraceForcement = BraceForcement.AddBraces; CSharpParser parser = new CSharpParser (); var compilationUnit = parser.Parse (data); TestErrors (parser); compilationUnit.AcceptVisitor (new AstIndentationVisitor (policy, data), null); System.Console.WriteLine (data.Document.Text); Assert.AreEqual (@"class Test { void TestMethod () { if (true) { // TestComment Call (); } } }", data.Document.Text); }
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; 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 MonoDevelop.CSharp.Parser.CSharpParser(); bool hadErrors = parser.ErrorReportPrinter.ErrorsCount + parser.ErrorReportPrinter.FatalCounter > 0; var compilationUnit = parser.Parse(stubData); var policy = policyParent.Get <CSharpFormattingPolicy> (mimeTypeChain); var domSpacingVisitor = new AstFormattingVisitor(policy, stubData) { AutoAcceptChanges = false, }; compilationUnit.AcceptVisitor(domSpacingVisitor, null); var changes = new List <Change> (); changes.AddRange(domSpacingVisitor.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 AstFormattingVisitor.MyTextReplaceChange) { ((AstFormattingVisitor.MyTextReplaceChange)change).SetTextEditorData(data.Editor); } 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 (parser.ErrorReportPrinter.Errors.Any(e => e.ErrorType == ErrorType.Error) || data.ParsedDocument.Errors.Any(e => e.ErrorType == ErrorType.Error)) { var lastOffset = data.Editor.Caret.Offset; changes.RemoveAll(c => ((TextReplaceChange)c).Offset > lastOffset); } RefactoringService.AcceptChanges(null, null, changes); foreach (int line in lines) { data.Editor.Document.CommitLineUpdate(line); } stubData.Dispose(); }