Esempio n. 1
0
		internal static IEnumerable<char> GetTextWithoutCommentsAndStrings (Mono.TextEditor.TextDocument doc, int start, int end) 
		{
			bool isInString = false, isInChar = false;
			bool isInLineComment = false, isInBlockComment = false;
			int escaping = 0;
			
			for (int pos = start; pos < end; pos++) {
				char ch = doc.GetCharAt (pos);
				switch (ch) {
					case '\r':
					case '\n':
						isInLineComment = false;
						break;
					case '/':
						if (isInBlockComment) {
							if (pos > 0 && doc.GetCharAt (pos - 1) == '*') 
								isInBlockComment = false;
						} else  if (!isInString && !isInChar && pos + 1 < doc.TextLength) {
							char nextChar = doc.GetCharAt (pos + 1);
							if (nextChar == '/')
								isInLineComment = true;
							if (!isInLineComment && nextChar == '*')
								isInBlockComment = true;
						}
						break;
					case '"':
						if (!(isInChar || isInLineComment || isInBlockComment))
							if (!isInString || escaping != 1)
								isInString = !isInString;
						break;
					case '\'':
						if (!(isInString || isInLineComment || isInBlockComment))
							if (!isInChar || escaping != 1)
								isInChar = !isInChar;
						break;
					case '\\':
						if (escaping != 1)
							escaping = 2;
						break;
					default :
						if (!(isInString || isInChar || isInLineComment || isInBlockComment))
							yield return ch;
						break;
				}
				escaping--;
			}
		}
Esempio n. 2
0
		static IEnumerable<KeyValuePair <char, int>> GetTextWithoutCommentsAndStrings (Mono.TextEditor.Document doc, int start, int end) 
		{
			bool isInString = false, isInChar = false;
			bool isInLineComment = false, isInBlockComment = false;
			
			for (int pos = start; pos < end; pos++) {
				char ch = doc.GetCharAt (pos);
				switch (ch) {
					case '\r':
					case '\n':
						isInLineComment = false;
						break;
					case '/':
						if (isInBlockComment) {
							if (pos > 0 && doc.GetCharAt (pos - 1) == '*') 
								isInBlockComment = false;
						} else  if (!isInString && !isInChar && pos + 1 < doc.Length) {
							char nextChar = doc.GetCharAt (pos + 1);
							if (nextChar == '/')
								isInLineComment = true;
							if (!isInLineComment && nextChar == '*')
								isInBlockComment = true;
						}
						break;
					case '"':
						if (!(isInChar || isInLineComment || isInBlockComment)) 
							isInString = !isInString;
						break;
					case '\'':
						if (!(isInString || isInLineComment || isInBlockComment)) 
							isInChar = !isInChar;
						break;
					default :
						if (!(isInString || isInChar || isInLineComment || isInBlockComment))
							yield return new KeyValuePair<char, int> (ch, pos);
						break;
				}
			}
		}
Esempio n. 3
0
		static void CheckLine (Mono.TextEditor.Document doc, Mono.TextEditor.LineSegment line, out bool isBlank, out bool isBracket)
		{
			isBlank = true;
			isBracket = false;
			for (int i = 0; i < line.Length; i++) {
				char c = doc.GetCharAt (line.Offset + i);
				if (c == '{') {
					isBracket = true;
					isBlank = false;
				}
				else if (!Char.IsWhiteSpace (c)) {
					isBlank = false;
					if (isBracket) {
						isBracket = false;
						break;
					}
				}
			}
		}
		public MonoDevelop.Projects.Dom.ResolveResult GetLanguageItem (ProjectDom dom, Mono.TextEditor.TextEditorData data, int offset)
		{
			if (offset < 0)
				return null;
			string fileName = data.Document.FileName;
			IParser parser = ProjectDomService.GetParser (fileName);
			if (parser == null)
				return null;
			
			MonoDevelop.Ide.Gui.Document doc = IdeApp.Workbench.ActiveDocument;
			if (doc == null)
				return null;
			
			IResolver         resolver = parser.CreateResolver (dom, doc, fileName);
			if (resolver == null) 
				return null;
			var expressionFinder = new NewCSharpExpressionFinder (dom);
			
			int wordEnd = Math.Min (offset, data.Length - 1);
			if (data.GetCharAt (wordEnd) == '@')
				wordEnd++;
			while (wordEnd < data.Length && (Char.IsLetterOrDigit (data.GetCharAt (wordEnd)) || data.GetCharAt (wordEnd) == '_'))
				wordEnd++;
			
			while (wordEnd < data.Length - 1 && Char.IsWhiteSpace (data.GetCharAt (wordEnd)))
				wordEnd++;
			/* is checked at the end.
			int saveEnd = wordEnd;
			if (wordEnd < data.Length && data.GetCharAt (wordEnd) == '<') {
				int matchingBracket = data.Document.GetMatchingBracketOffset (wordEnd);
				if (matchingBracket > 0)
					wordEnd = matchingBracket;
				while (wordEnd < data.Length - 1 && Char.IsWhiteSpace (data.GetCharAt (wordEnd)))
					wordEnd++;
			}
			
			bool wasMethodCall = false;
			if (data.GetCharAt (wordEnd) == '(') {
				int matchingBracket = data.Document.GetMatchingBracketOffset (wordEnd);
				if (matchingBracket > 0) {
					wordEnd = matchingBracket;
					wasMethodCall = true;
				}
			}
			if (!wasMethodCall)
				wordEnd = saveEnd;*/

			ExpressionResult expressionResult = expressionFinder.FindExpression (data, wordEnd);
			if (expressionResult == null)
				return null;
			
			ResolveResult resolveResult;
			DocumentLocation loc = data.Document.OffsetToLocation (offset);
			string savedExpression = null;
			
			// special handling for 'var' "keyword"
			if (expressionResult.ExpressionContext == ExpressionContext.IdentifierExpected && expressionResult.Expression != null && expressionResult.Expression.Trim () == "var") {
				int endOffset = data.Document.LocationToOffset (expressionResult.Region.End.Line, expressionResult.Region.End.Column);
				StringBuilder identifer = new StringBuilder ();
				for (int i = endOffset; i >= 0 && i < data.Document.Length; i++) {
					char ch = data.Document.GetCharAt (i);
					if (Char.IsWhiteSpace (ch))
						continue;
					if (ch == '=')
						break;
					if (Char.IsLetterOrDigit (ch) || ch =='_') {
						identifer.Append (ch);
						continue;
					}
					identifer.Length = 0;
					break;
				}
				if (identifer.Length > 0) {
					expressionResult.Expression = identifer.ToString ();
					resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line, loc.Column));
					if (resolveResult != null) {
						resolveResult = new MemberResolveResult (dom.GetType (resolveResult.ResolvedType));
						resolveResult.ResolvedExpression = expressionResult;
						return resolveResult;
					}
				}
			}
			if (expressionResult.ExpressionContext == ExpressionContext.Attribute) {
				savedExpression = expressionResult.Expression;
				expressionResult.Expression = expressionResult.Expression.Trim () + "Attribute";
				expressionResult.ExpressionContext = ExpressionContext.ObjectCreation;
			} 
			resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line, loc.Column));
			if (savedExpression != null && resolveResult == null) {
				expressionResult.Expression = savedExpression;
				resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line, loc.Column));
			}
			// Search for possible generic parameters.
//			if (this.resolveResult == null || this.resolveResult.ResolvedType == null || String.IsNullOrEmpty (this.resolveResult.ResolvedType.Name)) {
			if (!expressionResult.Region.IsEmpty) {
				int j = data.Document.LocationToOffset (expressionResult.Region.End.Line, expressionResult.Region.End.Column);
				int bracket = 0;
				for (int i = j; i >= 0 && i < data.Document.Length; i++) {
					char ch = data.Document.GetCharAt (i);
					if (Char.IsWhiteSpace (ch))
						continue;
					if (ch == '<') {
						bracket++;
					} else if (ch == '>') {
						bracket--;
						if (bracket == 0) {
							expressionResult.Expression += data.Document.GetTextBetween (j, i + 1);
							expressionResult.ExpressionContext = ExpressionContext.ObjectCreation;
							resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line, loc.Column));
							break;
						}
					} else {
						if (bracket == 0)
							break;
					}
				}
			}
			
			// To resolve method overloads the full expression must be parsed.
			// ex.: Overload (1)/ Overload("one") - parsing "Overload" gives just a MethodResolveResult
			// and for constructor initializers it's tried too to to resolve constructor overloads.
			if (resolveResult is ThisResolveResult || 
			    resolveResult is BaseResolveResult || 
			    resolveResult is MethodResolveResult && ((MethodResolveResult)resolveResult).Methods.Count > 1) {
				// put the search offset at the end of the invocation to be able to find the full expression
				// the resolver finds it itself if spaces are between the method name and the argument opening parentheses.
				while (wordEnd < data.Length - 1 && Char.IsWhiteSpace (data.GetCharAt (wordEnd)))
					wordEnd++;
				if (data.GetCharAt (wordEnd) == '(') {
					int matchingBracket = data.Document.GetMatchingBracketOffset (wordEnd);
					if (matchingBracket > 0)
						wordEnd = matchingBracket;
				}
				//Console.WriteLine (expressionFinder.FindFullExpression (txt, wordEnd));
				ResolveResult possibleResult = resolver.Resolve (expressionFinder.FindFullExpression (data, wordEnd), new DomLocation (loc.Line, loc.Column)) ?? resolveResult;
				//Console.WriteLine ("possi:" + resolver.Resolve (expressionFinder.FindFullExpression (txt, wordEnd), new DomLocation (loc.Line, loc.Column)));
				if (possibleResult is MethodResolveResult)
					resolveResult = possibleResult;
			}
			return resolveResult;
		}
		public MonoDevelop.Projects.Dom.ResolveResult GetLanguageItem (ProjectDom dom, Mono.TextEditor.TextEditorData data, int offset, string expression)
		{
			string fileName = data.Document.FileName;
			MonoDevelop.Ide.Gui.Document doc = IdeApp.Workbench.ActiveDocument;
			if (doc == null)
				return null;
			
			IParser parser = ProjectDomService.GetParser (fileName);
			if (parser == null)
				return null;
			
			IResolver         resolver = parser.CreateResolver (dom, doc, fileName);
			IExpressionFinder expressionFinder = parser.CreateExpressionFinder (dom);
			if (resolver == null || expressionFinder == null) 
				return null;
			int wordEnd = offset;
			while (wordEnd < data.Length && (Char.IsLetterOrDigit (data.GetCharAt (wordEnd)) || data.GetCharAt (wordEnd) == '_'))
				wordEnd++;
			ExpressionResult expressionResult = new ExpressionResult (expression);
			expressionResult.ExpressionContext = ExpressionContext.MethodBody;
			
			DocumentLocation loc = data.Document.OffsetToLocation (offset);
			string savedExpression = null;
			ResolveResult resolveResult;
			
			if (expressionResult.ExpressionContext == ExpressionContext.Attribute) {
				savedExpression = expressionResult.Expression;
				expressionResult.Expression += "Attribute";
				expressionResult.ExpressionContext = ExpressionContext.ObjectCreation;
			} 
			resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line, loc.Column));
			if (savedExpression != null && resolveResult == null) {
				expressionResult.Expression = savedExpression;
				resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line, loc.Column));
			}
			if (expressionResult.Region.End.IsEmpty)
				return resolveResult;
			// Search for possible generic parameters.
//			if (this.resolveResult == null || this.resolveResult.ResolvedType == null || String.IsNullOrEmpty (this.resolveResult.ResolvedType.Name)) {
				int j = data.Document.LocationToOffset (expressionResult.Region.End.Line, expressionResult.Region.End.Column);
				int bracket = 0;
				for (int i = j; i >= 0 && i < data.Document.Length; i++) {
					char ch = data.Document.GetCharAt (i);
					if (Char.IsWhiteSpace (ch))
						continue;
					if (ch == '<') {
						bracket++;
					} else if (ch == '>') {
						bracket--;
						if (bracket == 0) {
							expressionResult.Expression += data.Document.GetTextBetween (j, i + 1);
							expressionResult.ExpressionContext = ExpressionContext.ObjectCreation;
							resolveResult = resolver.Resolve (expressionResult, new DomLocation (loc.Line, loc.Column)) ?? resolveResult;
							break;
						}
					} else {
						if (bracket == 0)
							break;
					}
				}
//			}
			
			// To resolve method overloads the full expression must be parsed.
			// ex.: Overload (1)/ Overload("one") - parsing "Overload" gives just a MethodResolveResult
			if (resolveResult is MethodResolveResult) 
				resolveResult = resolver.Resolve (expressionFinder.FindFullExpression (data, wordEnd), new DomLocation (loc.Line, loc.Column)) ?? resolveResult;
			return resolveResult;
		}
 static bool IsBlankLine(Mono.TextEditor.TextDocument doc, Mono.TextEditor.DocumentLine line)
 {
     for (int i = 0; i < line.Length; i++) {
         if (!Char.IsWhiteSpace (doc.GetCharAt (line.Offset + i)))
             return false;
     }
     return true;
 }
	//	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"));
				}
			}
		}