Parse() static private method

static private Parse ( CompilerCompilationUnit top ) : MonoDevelop.CSharp.Ast.CompilationUnit
top Mono.CSharp.CompilerCompilationUnit
return MonoDevelop.CSharp.Ast.CompilationUnit
		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);
		}
Beispiel #5
0
        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();
        }