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<CompilationUnit> ();
			var parsedFile = doc.ParsedDocument.ParsedFile as CSharpParsedFile;
			var node       = unit.GetNodeAt<Expression> (loc.Line, loc.Column);
			if (unit == null || parsedFile == null || node == null)
				return "";
			
			return data.GetTextBetween (node.StartLocation, node.EndLocation);
		}
	//	string expression;
/*		IMember GetLanguageItem (Mono.TextEditor.Document document, LineSegment line, int offset, string expression)
		{
			string txt = document.Text;
			ExpressionResult expressionResult = new ExpressionResult (expression);
//			ExpressionResult expressionResult = expressionFinder.FindFullExpression (txt, offset);
			int lineNumber = document.OffsetToLineNumber (offset);
			expressionResult.Region = new DomRegion (lineNumber, offset - line.Offset, lineNumber, offset + expression.Length - line.Offset);
			expressionResult.ExpressionContext = ExpressionContext.IdentifierExpected;
			
			resolver = new NRefactoryResolver (ctx, doc.CompilationUnit, doc.TextEditor, document.FileName);
			ResolveResult result = resolver.Resolve (expressionResult, expressionResult.Region.Start);
			
			if (result is MemberResolveResult) 
				return ((MemberResolveResult)result).ResolvedMember;
			return null;
		}*/
		
		public override void Analyze (Mono.TextEditor.Document doc, LineSegment line, Chunk startChunk, int startOffset, int endOffset)
		{
			if (!MonoDevelop.Core.PropertyService.Get ("EnableSemanticHighlighting", false) || doc == null || line == null || startChunk == null)
				return;
			ctx = GetParserContext (doc);
			int lineNumber = doc.OffsetToLineNumber (line.Offset);
			ParsedDocument parsedDocument = ProjectDomService.GetParsedDocument (ctx, doc.FileName);
			ICompilationUnit unit = parsedDocument != null ? parsedDocument.CompilationUnit : null;
			if (unit == null)
				return;
			for (Chunk chunk = startChunk; chunk != null; chunk = chunk.Next) {
				if (chunk.Style != "text")
					continue;
				for (int i = chunk.Offset; i < chunk.EndOffset; i++) {
					char charBefore = i > 0 ? doc.GetCharAt (i - 1) : '}';
					if (Char.IsLetter (doc.GetCharAt (i)) && !Char.IsLetterOrDigit (charBefore)) {
					} else {
						continue;
					}
					
					int start = i;
					bool wasWhitespace = false;
					bool wasDot = false;
					int bracketCount = 0;
					while (start > 0) {
						char ch = doc.GetCharAt (start);
						if (ch == '\n' || ch == '\r')
							break;
						if (wasWhitespace && IsNamePart(ch)) {
							start++;
							if (start < chunk.Offset)
								start = Int32.MaxValue;
							break;
						}
						if (ch == '<') {
							bracketCount--;
							if (bracketCount < 0) {
								start++;
								break; 
							}
							start--;
							wasWhitespace = false;
							continue;
						}
						if (ch == '>') {
							if (wasWhitespace && !wasDot)
								break;
							bracketCount++;
							start--;
							wasWhitespace = false;
							continue;
						}
						if (!IsNamePart(ch) && !Char.IsWhiteSpace (ch) && ch != '.') {
							start++;
							break;
						}
						wasWhitespace = Char.IsWhiteSpace (ch);
						wasDot = ch == '.' || wasDot && wasWhitespace;
						start--;
					}
					
					int end = i;
					int genericCount = 0;
					wasWhitespace = false;
					List<Segment> nameSegments = new List<Segment> ();
					while (end < chunk.EndOffset) {
						char ch = doc.GetCharAt (end);
						if (wasWhitespace && IsNamePart(ch))
							break;
						if (ch == '<') {
							genericCount = 1;
							while (end < doc.Length) {
								ch = doc.GetCharAt (end);
								if (ch == ',')
									genericCount++;
								if (ch == '>') {
									nameSegments.Add (new Segment (end, 1));
									break;
								}
								end++;
							}
							break;
						}
						if (!IsNamePart(ch) && !Char.IsWhiteSpace (ch)) 
							break;
						wasWhitespace = Char.IsWhiteSpace (ch);
						end++;
					}
					if (start >= end) 
						continue;
					string typeString = doc.GetTextBetween (start, end);
					IReturnType returnType = NRefactoryResolver.ParseReturnType (new ExpressionResult (typeString));
						
					int nameEndOffset = start;
					for (; nameEndOffset < end; nameEndOffset++) {
						char ch = doc.GetCharAt (nameEndOffset);
						if (nameEndOffset >= i && ch == '<') {
							nameEndOffset++;
							break;
						}
					}
					nameSegments.Add (new Segment (i, nameEndOffset - i));

					int column = i - line.Offset;
					IType callingType = unit.GetTypeAt (lineNumber, column);
					List<IReturnType> genericParams = null;
					if (genericCount > 0) {
						genericParams = new List<IReturnType> ();
						for (int n = 0; n < genericCount; n++) 
							genericParams.Add (new DomReturnType ("A"));
					}
					
					IType type = null;
					if (ctx != null)
						type = ctx.SearchType ((MonoDevelop.Projects.Dom.INode)callingType ?? unit, returnType);
					if (type == null && unit != null && returnType != null)
						type = unit.GetType (returnType.FullName, returnType.GenericArguments.Count);
					if (ctx != null && type == null && returnType != null) {
						returnType.Name += "Attribute";
						type = ctx.SearchType ((MonoDevelop.Projects.Dom.INode)callingType ?? unit, returnType);
					}
					if (type != null)
						nameSegments.ForEach (segment => HighlightSegment (startChunk, segment, "keyword.semantic.type"));
				}
			}
		}