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;
		}
        public void InitializeCodeCompletion(char ch)
        {
            int caretOffset = Document.Editor.Caret.Offset;
            int start       = caretOffset - Tracker.Engine.CurrentStateLength;

            if (Document.Editor.GetCharAt(start) == '=')
            {
                start++;
            }
            string sourceText = Document.Editor.GetTextBetween(start, caretOffset);

            if (ch != '\0')
            {
                sourceText += ch;
            }
            string textAfterCaret = Document.Editor.GetTextBetween(caretOffset, Math.Min(Document.Editor.Length, Math.Max(caretOffset, Tracker.Engine.Position + Tracker.Engine.CurrentStateLength - 2)));

            if (documentBuilder == null)
            {
                localDocumentInfo = null;
                return;
            }
            localDocumentInfo = documentBuilder.BuildLocalDocument(documentInfo, Editor, sourceText, textAfterCaret, true);

            var viewContent = new MonoDevelop.Ide.Gui.HiddenTextEditorViewContent();

            viewContent.Project     = Document.Project;
            viewContent.ContentName = localDocumentInfo.ParsedLocalDocument.FileName;

            viewContent.Text = localDocumentInfo.LocalDocument;
            viewContent.GetTextEditorData().Caret.Offset = localDocumentInfo.CaretPosition;

            var workbenchWindow = new MonoDevelop.Ide.Gui.HiddenWorkbenchWindow();

            workbenchWindow.ViewContent      = viewContent;
            localDocumentInfo.HiddenDocument = new HiddenDocument(workbenchWindow)
            {
                HiddenParsedDocument = localDocumentInfo.ParsedLocalDocument
            };
        }
		CSharpCompletionTextEditorExtension CreateCompletion (Document realDocument, DocumentInfo info, LocalDocumentInfo localInfo, out CodeCompletionContext codeCompletionContext)
		{
			var doc = new TextDocument () {
				Text = localInfo.LocalDocument,
			};
			var documentLocation = doc.OffsetToLocation (localInfo.CaretPosition);
			
			codeCompletionContext = new CodeCompletionContext () {
				TriggerOffset = localInfo.CaretPosition,
				TriggerLine = documentLocation.Line,
				TriggerLineOffset = documentLocation.Column - 1
			};
			
			return new CSharpCompletionTextEditorExtension (localInfo.HiddenDocument) {
				CompletionWidget = CreateCompletionWidget (realDocument, localInfo)
			};
		}
			public AspCompletionWidget (Document realDocument, LocalDocumentInfo localInfo)
			{
				this.realDocument = realDocument;
				this.localInfo = localInfo;
			}
		public ICompletionWidget CreateCompletionWidget (Document realDocument, LocalDocumentInfo localInfo)
		{
			return new AspCompletionWidget (realDocument, localInfo);
		}
		public bool GetParameterCompletionCommandOffset (Document realDocument, DocumentInfo info, LocalDocumentInfo localInfo, out int cpos)
		{
			CodeCompletionContext codeCompletionContext;
			using (var completion = CreateCompletion (realDocument, info, localInfo, out codeCompletionContext)) {
				return completion.GetParameterCompletionCommandOffset (out cpos);
			}
		}
		public ParameterDataProvider HandleParameterCompletion (Document realDocument, CodeCompletionContext completionContext, DocumentInfo info, LocalDocumentInfo localInfo, char completionChar)
		{
			CodeCompletionContext ccc;
			using (var completion = CreateCompletion (realDocument, info, localInfo, out ccc)) {
				return completion.HandleParameterCompletion (completionContext, completionChar);
			}
		}
		public ICompletionDataList HandleCompletion (Document realDocument, CodeCompletionContext completionContext, DocumentInfo info, LocalDocumentInfo localInfo, char currentChar, ref int triggerWordLength)
		{
			CodeCompletionContext ccc;
			using (var completion = CreateCompletion (realDocument, info, localInfo, out ccc)) {
				return completion.HandleCodeCompletion (completionContext, currentChar, ref triggerWordLength);
			}
		}
		public ICompletionDataList HandlePopupCompletion (Document realDocument, DocumentInfo info, LocalDocumentInfo localInfo)
		{
			CodeCompletionContext codeCompletionContext;
			using (var completion = CreateCompletion (realDocument, info, localInfo, out codeCompletionContext)) {
				return completion.CodeCompletionCommand (codeCompletionContext);
			}
		}