GetTextBetween() public method

public GetTextBetween ( Mono.TextEditor.DocumentLocation start, Mono.TextEditor.DocumentLocation end ) : string
start Mono.TextEditor.DocumentLocation
end Mono.TextEditor.DocumentLocation
return string
Example #1
1
		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 GetExpression(Mono.TextEditor.TextEditorData data, int offset)
        {
            if (offset < 0)
            {
                return("");
            }
            var doc = IdeApp.Workbench.ActiveDocument;

            if (doc == null)
            {
                return("");
            }
            var loc        = RefactoringService.GetCorrectResolveLocation(doc, data.OffsetToLocation(offset));
            var unit       = doc.ParsedDocument.GetAst <SyntaxTree> ();
            var parsedFile = doc.ParsedDocument.ParsedFile as CSharpUnresolvedFile;
            var node       = unit.GetNodeAt <Expression> (loc.Line, loc.Column);

            if (unit == null || parsedFile == null || node == null)
            {
                return("");
            }

            return(data.GetTextBetween(node.StartLocation, node.EndLocation));
        }
Example #3
0
		public static string GetWordBeforeCaret (TextEditorData editor)
		{
			int offset = editor.Caret.Offset;
			int start  = FindPrevWordStart (editor, offset);
			return editor.GetTextBetween (start, offset);
		}
		ExpressionResult MakeResult (TextEditorData editor, int startOffset, int endOffset, IEnumerable<ExpressionContext> contexts)
		{
			if (endOffset < startOffset) {
				int tmp = startOffset;
				startOffset = endOffset;
				endOffset = tmp;
			}
			var start = editor.Document.OffsetToLocation (startOffset);
			var end = editor.Document.OffsetToLocation (endOffset);
			return new ExpressionResult (editor.GetTextBetween (startOffset, endOffset), new DomRegion (start.Line, start.Column, end.Line, end.Column), contexts);
		}
		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;
		}
Example #6
0
		protected override string InternalFormat (PolicyContainer policyParent, string mimeType, string input, int startOffset, int endOffset)
		{
			IEnumerable<string> types = DesktopService.GetMimeTypeInheritanceChain (CSharpFormatter.MimeType);
			
			TextEditorData data = new TextEditorData ();
			data.Text = input;
			data.Document.MimeType = mimeType;
			data.Document.SuppressHighlightUpdate = true;
			data.Document.FileName = "toformat.cs";
			var textPolicy = policyParent != null ? policyParent.Get<TextStylePolicy> (types) : MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<TextStylePolicy> (types);
			data.Options.TabsToSpaces = textPolicy.TabsToSpaces;
			data.Options.TabSize = textPolicy.TabWidth;
			data.Options.OverrideDocumentEolMarker = true;
			data.Options.DefaultEolMarker = textPolicy.GetEolMarker ();
			
			endOffset += CorrectFormatting (data, startOffset, endOffset);
			
			CSharp.Dom.CompilationUnit compilationUnit = new MonoDevelop.CSharp.Parser.CSharpParser ().Parse (data);
			CSharpFormattingPolicy policy = policyParent != null ? policyParent.Get<CSharpFormattingPolicy> (types) : MonoDevelop.Projects.Policies.PolicyService.GetDefaultPolicy<CSharpFormattingPolicy> (types);
			
			DomSpacingVisitor domSpacingVisitor = new DomSpacingVisitor (policy, data);
			domSpacingVisitor.AutoAcceptChanges = false;
			compilationUnit.AcceptVisitor (domSpacingVisitor, null);
			
			DomIndentationVisitor domIndentationVisitor = new DomIndentationVisitor (policy, data);
			domIndentationVisitor.AutoAcceptChanges = false;
			compilationUnit.AcceptVisitor (domIndentationVisitor, null);
			
			List<Change> 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;
			}
			string result = data.GetTextBetween (startOffset, end);
			return result;
		}
		public string BuildDocumentString (DocumentInfo info, TextEditorData data, List<LocalDocumentInfo.OffsetInfo> offsetInfos = null, bool buildExpressions = false)
		{
			var document = new StringBuilder ();
			
			WriteUsings (info.Imports, document);

			foreach (var node in info.XScriptBlocks) {
				var start = data.Document.LocationToOffset (node.Region.Begin.Line, node.Region.Begin.Column) + 2;
				var end = data.Document.LocationToOffset (node.Region.End.Line, node.Region.End.Column) - 2;
				if (offsetInfos != null)
					offsetInfos.Add (new LocalDocumentInfo.OffsetInfo (start, document.Length, end - start));
				
				document.AppendLine (data.Document.GetTextBetween (start, end));
			}
			if (buildExpressions) {
				WriteClassDeclaration (info, document);
				document.AppendLine ("{");
				document.AppendLine ("void Generated ()");
				document.AppendLine ("{");
				//Console.WriteLine ("start:" + location.BeginLine  +"/" +location.BeginColumn);

				foreach (var node in info.XExpressions) {
					bool isBlock = node is WebFormsRenderBlock;

					var start = data.Document.LocationToOffset (node.Region.Begin.Line, node.Region.Begin.Column) + 2;
					var end = data.Document.LocationToOffset (node.Region.End.Line, node.Region.End.Column) - 2;
					
					if (!isBlock) {
						document.Append ("WriteLine (");
						start += 1;
					}
					
					string expr = data.GetTextBetween (start, end);
					if (offsetInfos != null) {
						offsetInfos.Add (new LocalDocumentInfo.OffsetInfo (start, document.Length, expr.Length));
					}
					document.Append (expr);
					if (!isBlock)
						document.Append (");");
				}
				document.AppendLine ("}");
				document.AppendLine ("}");
			}
			return document.ToString ();
		}
		public static bool GuessSemicolonInsertionOffset (TextEditorData data, ISegment curLine, int caretOffset, out int outOffset)
		{
			int lastNonWsOffset = caretOffset;
			char lastNonWsChar = '\0';
			outOffset = caretOffset;

			int max = curLine.EndOffset;

			int end = caretOffset;
			while (end > 1 && char.IsWhiteSpace (data.GetCharAt (end)))
				end--;
			int end2 = end;
			while (end2 > 1 && char.IsLetter (data.GetCharAt (end2 - 1)))
				end2--;
			if (end != end2) {
				string token = data.GetTextBetween (end2, end + 1);
				// guess property context
				if (token == "get" || token == "set")
					return false;
			}

			var offset = curLine.Offset;
			string lineText = data.GetTextAt (caretOffset, max - caretOffset);
			var lexer = new CSharpCompletionEngineBase.MiniLexer (lineText);
			lexer.Parse ((ch, i) => {
				if (lexer.IsInSingleComment || lexer.IsInMultiLineComment)
					return true;
				if (ch == '}' && lexer.IsFistNonWs && !IsSemicolonalreadyPlaced (data, caretOffset)) {
					lastNonWsChar = ';';
					return true;
				}
				if (!char.IsWhiteSpace (ch)) {
					lastNonWsOffset = caretOffset + i;
					lastNonWsChar = ch;
				}
				return false;
			}); 
			// if the line ends with ';' the line end is not the correct place for a new semicolon.
			if (lastNonWsChar == ';')
				return false;
			outOffset = lastNonWsOffset;
			return true;
		}
		static string GetIdentifierName (TextEditorData editor, Identifier id, out int startOffset)
		{
			startOffset = editor.LocationToOffset (id.StartLocation.Line, id.StartLocation.Column);

			return editor.GetTextBetween (id.StartLocation, id.EndLocation);
		}
		public static string ResolveExpression (TextEditorData editor, ResolveResult result, AstNode node, out int startOffset)
		{
			//Console.WriteLine ("result is a {0}", result.GetType ().Name);
			startOffset = -1;

			if (result is NamespaceResolveResult ||
			    result is ConversionResolveResult ||
			    result is ConstantResolveResult ||
			    result is ForEachResolveResult ||
			    result is TypeIsResolveResult ||
			    result is TypeOfResolveResult ||
			    result is ErrorResolveResult)
				return null;

			if (result.IsCompileTimeConstant)
				return null;

			startOffset = editor.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column);

			if (result is InvocationResolveResult) {
				var ir = (InvocationResolveResult) result;
				if (ir.Member.Name == ".ctor") {
					// if the user is hovering over something like "new Abc (...)", we want to show them type information for Abc
					return ir.Member.DeclaringType.FullName;
				}

				// do not support general method invocation for tooltips because it could cause side-effects
				return null;
			} else if (result is LocalResolveResult) {
				if (node is ParameterDeclaration) {
					// user is hovering over a method parameter, but we don't want to include the parameter type
					var param = (ParameterDeclaration) node;

					return GetIdentifierName (editor, param.NameToken, out startOffset);
				}

				if (node is VariableInitializer) {
					// user is hovering over something like "int fubar = 5;", but we don't want the expression to include the " = 5"
					var variable = (VariableInitializer) node;

					return GetIdentifierName (editor, variable.NameToken, out startOffset);
				}
			} else if (result is MemberResolveResult) {
				var mr = (MemberResolveResult) result;

				if (node is PropertyDeclaration) {
					var prop = (PropertyDeclaration) node;
					var name = GetIdentifierName (editor, prop.NameToken, out startOffset);

					// if the property is static, then we want to return "Full.TypeName.Property"
					if (prop.Modifiers.HasFlag (Modifiers.Static))
						return mr.Member.DeclaringType.FullName + "." + name;

					// otherwise we want to return "this.Property" so that it won't conflict with anything else in the local scope
					return "this." + name;
				}

				if (node is FieldDeclaration) {
					var field = (FieldDeclaration) node;
					var name = GetIdentifierName (editor, field.NameToken, out startOffset);

					// if the field is static, then we want to return "Full.TypeName.Field"
					if (field.Modifiers.HasFlag (Modifiers.Static))
						return mr.Member.DeclaringType.FullName + "." + name;

					// otherwise we want to return "this.Field" so that it won't conflict with anything else in the local scope
					return "this." + name;
				}

				if (node is VariableInitializer) {
					// user is hovering over a field declaration that includes initialization
					var variable = (VariableInitializer) node;
					var name = GetIdentifierName (editor, variable.NameToken, out startOffset);

					// walk up the AST to find the FieldDeclaration so that we can determine if it is static or not
					var field = variable.GetParent<FieldDeclaration> ();

					// if the field is static, then we want to return "Full.TypeName.Field"
					if (field.Modifiers.HasFlag (Modifiers.Static))
						return mr.Member.DeclaringType.FullName + "." + name;

					// otherwise we want to return "this.Field" so that it won't conflict with anything else in the local scope
					return "this." + name;
				}

				if (node is NamedExpression) {
					// user is hovering over 'Property' in an expression like: var fubar = new Fubar () { Property = baz };
					var variable = node.GetParent<VariableInitializer> ();
					if (variable != null) {
						var variableName = GetIdentifierName (editor, variable.NameToken, out startOffset);
						var name = GetIdentifierName (editor, ((NamedExpression) node).NameToken, out startOffset);

						return variableName + "." + name;
					}
				}
			} else if (result is TypeResolveResult) {
				return ((TypeResolveResult) result).Type.FullName;
			}

			return editor.GetTextBetween (node.StartLocation, node.EndLocation);
		}
		static string GetLocalExpression (TextEditorData editor, LocalResolveResult lr, DomRegion expressionRegion)
		{
			var start = new DocumentLocation (expressionRegion.BeginLine, expressionRegion.BeginColumn);
			var end   = new DocumentLocation (expressionRegion.EndLine, expressionRegion.EndColumn);

			// In a setter, the 'value' variable will have a begin line/column of 0,0 which is an undefined offset
			if (lr.Variable.Region.BeginLine != 0 && lr.Variable.Region.BeginColumn != 0) {
				// Use the start and end offsets of the variable region so that we get the "@" in variable names like "@class"
				start = new DocumentLocation (lr.Variable.Region.BeginLine, lr.Variable.Region.BeginColumn);
				end = new DocumentLocation (lr.Variable.Region.EndLine, lr.Variable.Region.EndColumn);
			}

			string expression = editor.GetTextBetween (start, end).Trim ();

			// Note: When the LocalResolveResult is a parameter, the Variable.Region includes the type
			if (lr.IsParameter) {
				int index = IndexOfLastWhiteSpace (expression);
				if (index != -1)
					expression = expression.Substring (index + 1);
			}

			return expression;
		}
		internal static bool TryResolveExpression (TextEditorData editor, ResolveResult res, DomRegion expressionRegion, out string expression)
		{
			expression = null;

			//Console.WriteLine ("res is a {0}", res.GetType ().Name);

			if (expressionRegion.IsEmpty)
				return false;

			if (res is NamespaceResolveResult ||
			    res is ConversionResolveResult ||
			    res is ConstantResolveResult ||
			    res is ForEachResolveResult ||
			    res is TypeIsResolveResult ||
			    res is TypeOfResolveResult ||
			    res is ErrorResolveResult)
				return false;

			if (res.IsCompileTimeConstant)
				return false;

			var start = new DocumentLocation (expressionRegion.BeginLine, expressionRegion.BeginColumn);
			var end   = new DocumentLocation (expressionRegion.EndLine, expressionRegion.EndColumn);

			if (res is LocalResolveResult) {
				expression = GetLocalExpression (editor, (LocalResolveResult) res, expressionRegion);
			} else if (res is InvocationResolveResult) {
				var ir = (InvocationResolveResult) res;

				if (ir.Member.Name != ".ctor")
					return false;

				expression = ir.Member.DeclaringType.FullName;
			} else if (res is MemberResolveResult) {
				expression = GetMemberExpression (editor, (MemberResolveResult) res, expressionRegion);
			} else if (res is NamedArgumentResolveResult) {
				expression = editor.GetTextBetween (start, end);
			} else if (res is ThisResolveResult) {
				expression = editor.GetTextBetween (start, end);
			} else if (res is TypeResolveResult) {
				expression = editor.GetTextBetween (start, end);
			} else {
				return false;
			}

			return true;
		}
		static string GetMemberExpression (TextEditorData editor, MemberResolveResult mr, DomRegion expressionRegion)
		{
			string expression = null;
			string member = null;

			if (mr.Member != null) {
				if (mr.Member is IProperty) {
					// Visual Studio will evaluate Properties if you hover over their definitions...
					var prop = (IProperty) mr.Member;

					if (prop.CanGet) {
						if (prop.IsStatic)
							expression = prop.FullName;
						else
							member = prop.Name;
					} else {
						return null;
					}
				} else if (mr.Member is IField) {
					var field = (IField) mr.Member;

					if (field.IsStatic)
						expression = field.FullName;
					else
						member = field.Name;
				} else {
					return null;
				}
			} else {
				return null;
			}

			if (expression == null) {
				if (mr.TargetResult != null) {
					var targetRegion = mr.TargetResult.GetDefinitionRegion ();

					if (mr.TargetResult is LocalResolveResult) {
						expression = GetLocalExpression (editor, (LocalResolveResult) mr.TargetResult, targetRegion);
					} else if (mr.TargetResult is MemberResolveResult) {
						expression = GetMemberExpression (editor, (MemberResolveResult) mr.TargetResult, targetRegion);
					} else if (mr.TargetResult is InitializedObjectResolveResult) {
						return null;
					} else if (mr.TargetResult is ThisResolveResult) {
						return "this." + member;
					} else if (!targetRegion.IsEmpty) {
						var start = new DocumentLocation (targetRegion.BeginLine, targetRegion.BeginColumn);
						var end   = new DocumentLocation (targetRegion.EndLine, targetRegion.EndColumn);
						expression = editor.GetTextBetween (start, end).Trim ();
					}

					if (expression == null) {
						var start = new DocumentLocation (expressionRegion.BeginLine, expressionRegion.BeginColumn);
						var end   = new DocumentLocation (expressionRegion.EndLine, expressionRegion.EndColumn);
						return editor.GetTextBetween (start, end).Trim ();
					}
				}

				if (!string.IsNullOrEmpty (expression))
					expression += "." + member;
				else
					expression = member;
			}

			return expression;
		}
		public static bool GuessSemicolonInsertionOffset (TextEditorData data, IDocumentLine curLine, int caretOffset, out int outOffset)
		{
			int lastNonWsOffset = caretOffset;
			char lastNonWsChar = '\0';
			outOffset = caretOffset;
			int max = curLine.EndOffset;
	//		if (caretOffset - 2 >= curLine.Offset && data.Document.GetCharAt (caretOffset - 2) == ')' && !IsSemicolonalreadyPlaced (data, caretOffset))
	//			return false;

			int end = caretOffset;
			while (end > 1 && char.IsWhiteSpace (data.GetCharAt (end)))
				end--;
			int end2 = end;
			while (end2 > 1 && char.IsLetter(data.GetCharAt (end2 - 1)))
				end2--;
			if (end != end2) {
				string token = data.GetTextBetween (end2, end + 1);
				// guess property context
				if (token == "get" || token == "set")
					return false;
			}

			bool isInString = false , isInChar= false , isVerbatimString= false;
			bool isInLineComment = false , isInBlockComment= false;
			bool firstChar = true;
			for (int pos = caretOffset; pos < max; pos++) {
				if (pos == caretOffset) {
					if (isInString || isInChar || isVerbatimString || isInLineComment || isInBlockComment) {
						outOffset = pos;
						return true;
					}
				}
				char ch = data.Document.GetCharAt (pos);
				switch (ch) {
				case '}':
					if (firstChar && !IsSemicolonalreadyPlaced (data, caretOffset))
						return false;
					break;
				case '/':
					if (isInBlockComment) {
						if (pos > 0 && data.Document.GetCharAt (pos - 1) == '*') 
							isInBlockComment = false;
					} else if (!isInString && !isInChar && pos + 1 < max) {
						char nextChar = data.Document.GetCharAt (pos + 1);
						if (nextChar == '/') {
							outOffset = lastNonWsOffset;
							return true;
						}
						if (!isInLineComment && nextChar == '*') {
							outOffset = lastNonWsOffset;
							return true;
						}
					}
					break;
				case '\\':
					if (isInChar || (isInString && !isVerbatimString))
						pos++;
					break;
				case '@':
					if (!(isInString || isInChar || isInLineComment || isInBlockComment) && pos + 1 < max && data.Document.GetCharAt (pos + 1) == '"') {
						isInString = true;
						isVerbatimString = true;
						pos++;
					}
					break;
				case '"':
					if (!(isInChar || isInLineComment || isInBlockComment)) {
						if (isInString && isVerbatimString && pos + 1 < max && data.Document.GetCharAt (pos + 1) == '"') {
							pos++;
						} else {
							isInString = !isInString;
							isVerbatimString = false;
						}
					}
					break;
				case '\'':
					if (!(isInString || isInLineComment || isInBlockComment)) 
						isInChar = !isInChar;
					break;
				}
				if (!char.IsWhiteSpace (ch)) {
					firstChar = false;
					lastNonWsOffset = pos;
					lastNonWsChar = ch;
				}
			}
			// if the line ends with ';' the line end is not the correct place for a new semicolon.
			if (lastNonWsChar == ';')
				return false;
			outOffset = lastNonWsOffset;
			return true;
		}
		public LocalDocumentInfo BuildLocalDocument (DocumentInfo info, TextEditorData data,
		                                             string expressionText, string textAfterCaret, bool isExpression)
		{
			var sb = new StringBuilder ();
			
			WriteUsings (info.Imports, sb);
			WriteClassDeclaration (info, sb);
			sb.AppendLine ("{");
			var result = new LocalDocumentInfo ();
			if (isExpression) {
				sb.AppendLine ("void Generated ()");
				sb.AppendLine ("{");
				//Console.WriteLine ("start:" + location.BeginLine  +"/" +location.BeginColumn);
				foreach (var node in info.XExpressions) {
					bool isBlock = node is WebFormsRenderBlock;

					if (node.Region.Begin.Line > data.Caret.Line || node.Region.Begin.Line == data.Caret.Line && node.Region.Begin.Column > data.Caret.Column - 5) 
						continue;
					//Console.WriteLine ("take xprt:" + expressions.Key.BeginLine  +"/" +expressions.Key.BeginColumn);

					var start = data.Document.LocationToOffset (node.Region.Begin.Line, node.Region.Begin.Column) + 2;
					var end = data.Document.LocationToOffset (node.Region.End.Line, node.Region.End.Column) - 2;

					if (!isBlock) {
						sb.Append ("WriteLine (");
						start += 1;
					}

					string expr = data.GetTextBetween (start, end);
					result.AddTextPosition (start, end, expr.Length);
					sb.Append (expr);

					if (!isBlock)
						sb.Append (");");
				}
			}
			sb.Append (expressionText);
			int caretPosition = sb.Length;
			sb.Append (textAfterCaret);
			
			sb.AppendLine ();
			sb.AppendLine ("}");
			sb.AppendLine ("}");
			
			result.LocalDocument = sb.ToString ();
			result.CaretPosition = caretPosition;
			result.OriginalCaretPosition = data.Caret.Offset;
			result.ParsedLocalDocument = Parse (info.AspNetDocument.FileName, sb.ToString ());
			return result;
		}
Example #16
0
		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;
		}
        //
        // TODO - It seems the support for properties varies
        // depending on the ECMA script requested version.
        // Fix the code here.
        //
        public static int GuessSemicolonInsertionOffset(TextEditorData data, DocumentLine currLine, int caretOffset)
        {
            int lastNonWsOffset = caretOffset;
            char lastNonWsChar = '\0';
            int max = currLine.EndOffset;

            // PORT NOTE: Honestly, this looks like a hack.
            if (caretOffset - 2 >= currLine.Offset && data.Document.GetCharAt (caretOffset - 2) == ')')
                return caretOffset;

            int end = caretOffset;
            while (end > 1 && Char.IsWhiteSpace (data.GetCharAt (end)))
                end--;

            int end2 = end;
            while (end2 > 1 && Char.IsLetter (data.GetCharAt (end2 - 1)))
                end2--;

            if (end != end2) {
                string token = data.GetTextBetween (end2, end + 1);
                // guess property context
                if (token == "get" || token == "set")
                    return caretOffset;
            }

            bool isInDQuotedString = false, isInSQuotedString = false;
            bool isInLineComment = false , isInBlockComment = false;

            // Compare the first check against the original one.
            for (int pos = caretOffset; pos < max; pos++) {
                if (pos == caretOffset) {
                    if (isInDQuotedString || isInSQuotedString || isInLineComment || isInBlockComment)
                        return pos;
                }

                char ch = data.Document.GetCharAt (pos);
                switch (ch) {
                case '/':
                    if (isInBlockComment) {
                        if (pos > 0 && data.Document.GetCharAt (pos - 1) == '*')
                            isInBlockComment = false;

                    } else if (!(isInDQuotedString || isInSQuotedString) && pos + 1 < max) {
                        char nextChar = data.Document.GetCharAt (pos + 1);
                        if (nextChar == '/') {
                            isInLineComment = true;
                            return lastNonWsOffset;
                        }
                        if (!isInLineComment && nextChar == '*') {
                            isInBlockComment = true;
                            return lastNonWsOffset;
                        }
                    }

                    break;
                case '\\':
                    if (isInSQuotedString || isInDQuotedString)
                        pos++;

                    break;
                case '"':
                    if (!(isInSQuotedString || isInLineComment || isInBlockComment)) {
                        if (isInDQuotedString && pos + 1 < max && data.Document.GetCharAt (pos + 1) == '"')
                            pos++;
                        else
                            isInDQuotedString = !isInDQuotedString;
                    }

                    break;
                case '\'':
                    if (!(isInDQuotedString || isInLineComment || isInBlockComment))
                        isInSQuotedString = !isInSQuotedString;

                    break;
                }

                if (!Char.IsWhiteSpace (ch)) {
                    lastNonWsOffset = pos;
                    lastNonWsChar = ch;
                }
            }

            // if the line ends with ';' the line end is not the correct place for a new semicolon.
            if (lastNonWsChar == ';')
                return caretOffset;

            return lastNonWsOffset;
        }