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; } } }
void TestCreateMethod (string input, string outputString, bool returnWholeFile) { var generator = new CSharpCodeGeneratorNode (); MonoDevelop.Projects.CodeGeneration.CodeGenerator.AddGenerator (generator); var refactoring = new CreateMethodCodeGenerator (); RefactoringOptions options = ExtractMethodTests.CreateRefactoringOptions (input); Assert.IsTrue (refactoring.IsValid (options)); if (returnWholeFile) { refactoring.SetInsertionPoint (CodeGenerationService.GetInsertionPoints (options.Document, refactoring.DeclaringType).First ()); } else { DocumentLocation loc = new DocumentLocation (1, 1); refactoring.SetInsertionPoint (new InsertionPoint (loc, NewLineInsertion.Eol, NewLineInsertion.Eol)); } List<Change> changes = refactoring.PerformChanges (options, null); // changes.ForEach (c => Console.WriteLine (c)); // get just the generated method. string output = ExtractMethodTests.GetOutput (options, changes); if (returnWholeFile) { Assert.IsTrue (ExtractMethodTests.CompareSource (output, outputString), "Expected:" + Environment.NewLine + outputString + Environment.NewLine + "was:" + Environment.NewLine + output); return; } output = output.Substring (0, output.IndexOf ('}') + 1).Trim (); // crop 1 level of indent Document doc = new Document (output); foreach (LineSegment line in doc.Lines) { if (doc.GetCharAt (line.Offset) == '\t') ((IBuffer)doc).Remove (line.Offset, 1); } output = doc.Text; Assert.IsTrue (ExtractMethodTests.CompareSource (output, outputString), "Expected:" + Environment.NewLine + outputString + Environment.NewLine + "was:" + Environment.NewLine + output); MonoDevelop.Projects.CodeGeneration.CodeGenerator.RemoveGenerator (generator); }
int FindNextWordOffset (Document doc, int offset, bool subword) { int lineNumber = doc.OffsetToLineNumber (offset); LineSegment line = doc.GetLine (lineNumber); if (line == null) return offset; int result = offset; int endOffset = line.Offset + line.EditableLength; if (result == endOffset) { line = doc.GetLine (lineNumber + 1); if (line != null) result = line.Offset; return result; } CharacterClass current = GetCharacterClass (doc.GetCharAt (result), subword, false); while (result < endOffset) { CharacterClass next = GetCharacterClass (doc.GetCharAt (result), subword, false); if (next != current) { // camelCase and PascalCase handling bool camelSkip = false; if (next == CharacterClass.LowercaseLetter && current == CharacterClass.UppercaseLetter) { if (result-2 > line.Offset) { CharacterClass previous = GetCharacterClass (doc.GetCharAt (result-2), subword, false); if (previous == CharacterClass.UppercaseLetter && result-2 > offset) result--; else camelSkip = true; } } if (!camelSkip) break; } current = next; result++; } while (result < endOffset && GetCharacterClass (doc.GetCharAt (result), subword, false) == CharacterClass.Whitespace) { result++; } return result; }
int FindNextWordOffset (Document doc, int offset, bool subword) { if (offset + 1 >= doc.Length) return doc.Length; int result = offset + 1; CC previous = SW.GetCharacterClass (doc.GetCharAt (result), subword, treat_); bool inIndentifier = previous != CC.Unknown && previous != CC.Whitespace; while (result < doc.Length) { char ch = doc.GetCharAt (result); CC current = SW.GetCharacterClass (ch, subword, treat_); //camelCase / PascalCase splitting if (subword) { if (current == CC.Digit && (previous != CC.Digit || (result-1 == offset && !Char.IsDigit (doc.GetCharAt (result-1))))) { break; } else if (previous == CC.Digit && current != CC.Digit) { break; } else if (current == CC.UppercaseLetter && previous != CC.UppercaseLetter) { break; } else if (current == CC.LowercaseLetter && previous == CC.UppercaseLetter && result - 2 > 0 && SW.GetCharacterClass (doc.GetCharAt (result - 2), subword, treat_) != CC.LowercaseLetter) { result--; break; } } //else break at end of identifiers if (previous != CC.Unknown && previous != CC.Whitespace) { inIndentifier = true; } else if (inIndentifier) { result--; break; } previous = current; result++; } foreach (FoldSegment segment in doc.GetFoldingsFromOffset (result)) { if (segment.IsFolded) result = System.Math.Max (result, segment.EndLine.Offset + segment.EndColumn); } return result; }
static int GetHomeMark (Document document, LineSegment line) { int result; for (result = 0; result < line.EditableLength; result++) if (!Char.IsWhiteSpace (document.GetCharAt (line.Offset + result))) return result; return result; }
static InsertionPoint GetInsertionPosition (Document doc, int line, int column) { int bodyEndOffset = doc.LocationToOffset (line, column) + 1; LineSegment curLine = doc.GetLine (line); if (curLine != null) { if (bodyEndOffset < curLine.Offset + curLine.EditableLength) { System.Console.WriteLine (1); // case1: positition is somewhere inside the start line return new InsertionPoint (new DocumentLocation (line, column + 1), NewLineInsertion.BlankLine, NewLineInsertion.BlankLine); } } // -> if position is at line end check next line LineSegment nextLine = doc.GetLine (line + 1); if (nextLine == null) // check for 1 line case. return new InsertionPoint (new DocumentLocation (line, column + 1), NewLineInsertion.BlankLine, NewLineInsertion.BlankLine); for (int i = nextLine.Offset; i < nextLine.EndOffset; i++) { char ch = doc.GetCharAt (i); if (!char.IsWhiteSpace (ch)) { // case2: next line contains non ws chars. System.Console.WriteLine (2); return new InsertionPoint (new DocumentLocation (line + 1, 1), NewLineInsertion.BlankLine, NewLineInsertion.BlankLine); } } // case3: whitespace line return new InsertionPoint (new DocumentLocation (line + 1, 1), NewLineInsertion.BlankLine, NewLineInsertion.None); }
public char GetCharAt(int position) { return(document.GetCharAt(position)); }
public virtual char GetCharAt (Document doc, int offset) { return doc.GetCharAt (offset); }
public static List<InsertionPoint> GetInsertionPoints (Document doc, IType type) { if (doc == null) throw new ArgumentNullException ("doc"); if (type == null) throw new ArgumentNullException ("type"); List<InsertionPoint> result = new List<InsertionPoint> (); int offset = doc.LocationToOffset (type.BodyRegion.Start.Line, type.BodyRegion.Start.Column); if (offset < 0) return result; while (offset < doc.Length && doc.GetCharAt (offset) != '{' && char.IsWhiteSpace (doc.GetCharAt (offset))) offset++; var realStartLocation = doc.OffsetToLocation (offset); result.Add (GetInsertionPosition (doc, realStartLocation.Line, realStartLocation.Column)); result[0].LineBefore = NewLineInsertion.None; foreach (IMember member in type.Members) { DomLocation domLocation = member.BodyRegion.End; if (domLocation.Line <= 0) { LineSegment lineSegment = doc.GetLine (member.Location.Line); if (lineSegment == null) continue; domLocation = new DomLocation (member.Location.Line, lineSegment.EditableLength + 1); } result.Add (GetInsertionPosition (doc, domLocation.Line, domLocation.Column)); } result[result.Count - 1].LineAfter = NewLineInsertion.None; CheckStartPoint (doc, result[0], result.Count == 1); if (result.Count > 1) CheckEndPoint (doc, result[result.Count - 1], result.Count == 1); return result; }
/// <summary> /// This method gets the line indentation. /// </summary> /// <param name="doc"> /// The <see cref="Document"/> the line belongs to. /// </param> /// <returns> /// The indentation of the line (all whitespace chars up to the first non ws char). /// </returns> public string GetIndentation (Document doc) { var result = new StringBuilder (); int offset = Offset; int max = System.Math.Min (offset + Length, doc.Length); for (int i = offset; i < max; i++) { char ch = doc.GetCharAt (i); if (ch != ' ' && ch != '\t') break; result.Append (ch); } return result.ToString (); }
static InsertionPoint GetInsertionPosition (Document doc, int line, int column) { LineSegment nextLine = doc.GetLine (line + 1); int bodyEndOffset = doc.LocationToOffset (line, column) + 1; int endOffset = nextLine != null ? nextLine.Offset : doc.Length; for (int i = bodyEndOffset; i < endOffset; i++) { char ch = doc.GetCharAt (i); if (!char.IsWhiteSpace (ch)) return new InsertionPoint (doc.OffsetToLocation (i), true, true); } if (nextLine == null) return new InsertionPoint (doc.OffsetToLocation (bodyEndOffset - 1), true, true); int oldLine = line; bool curLineEmpty = false; if (doc.GetLineIndent (nextLine).Length == nextLine.EditableLength) { curLineEmpty = true; while (line + 2 < doc.LineCount && doc.GetLineIndent (line + 2).Length == doc.GetLine (line + 2).EditableLength) line++; } bool insertBefore = !curLineEmpty && line - oldLine <= 1; bool insertAfter = line - oldLine == 0; // if (curLineEmpty) // line++; int lineNumber = line + 1; return new InsertionPoint (new DocumentLocation (lineNumber, doc.GetLineIndent (lineNumber).Length), insertBefore, insertAfter); }
internal static int ScanWord (Document doc, int offset, bool forwardDirection) { if (offset < 0 || offset >= doc.Length) return offset; var line = doc.GetLineByOffset (offset); char first = doc.GetCharAt (offset); while (offset >= line.Offset && offset < line.Offset + line.EditableLength) { char ch = doc.GetCharAt (offset); if (char.IsWhiteSpace (first) && !char.IsWhiteSpace (ch) || IsNoLetterOrDigit (first) && !IsNoLetterOrDigit (ch) || (char.IsLetterOrDigit (first) || first == '_') && !(char.IsLetterOrDigit (ch) || ch == '_')) break; offset = forwardDirection ? offset + 1 : offset - 1; } return System.Math.Min (line.Offset + line.EditableLength, System.Math.Max (line.Offset, offset + (forwardDirection ? 0 : 1))); }
int FindPrevWordOffset (Document doc, int offset, bool subword) { int lineNumber = doc.OffsetToLineNumber (offset); LineSegment line = doc.GetLine (lineNumber); if (line == null) return offset; int result = offset; if (result == line.Offset) { line = doc.GetLine (lineNumber - 1); if (line != null) result = line.Offset + line.EditableLength; return result; } CharacterClass current = GetCharacterClass (doc.GetCharAt (result - 1), subword, false); if (current == CharacterClass.Whitespace && result - 1 > line.Offset) { result--; current = GetCharacterClass (doc.GetCharAt (result - 2), subword, false); } while (result > line.Offset) { CharacterClass prev = GetCharacterClass (doc.GetCharAt (result - 1), subword, false); if (prev != current) { // camelCase and PascalCase handling bool camelSkip = false; if (prev == CharacterClass.UppercaseLetter && current == CharacterClass.LowercaseLetter) { if (result-2 > line.Offset) { CharacterClass back2 = GetCharacterClass (doc.GetCharAt (result-2), subword, false); if (back2 == CharacterClass.UppercaseLetter) result--; else camelSkip = true; } } if (!camelSkip) break; } current = prev; result--; } return result; }
public int SearchMatchingBracketForward (System.ComponentModel.BackgroundWorker worker, Document document, int offset, char openBracket, char closingBracket) { bool isInBlockComment = false; bool isInLineComment = false; int curStringQuote = -1; bool startsInLineComment = StartsInLineComment (document, offset); List<string> lineComments = GetList (document, "LineComment"); List<string> blockCommentStarts = GetList (document, "BlockCommentStart"); List<string> blockCommentEnds = GetList (document, "BlockCommentEnd"); List<string> stringQuotes = GetList (document, "StringQuote"); int depth = -1; while (offset >= 0 && offset < document.Length) { if (worker != null && worker.CancellationPending) return -1; if (curStringQuote < 0) { // check line comments if (!isInBlockComment && !isInLineComment) isInLineComment = StartsWithListMember (document, lineComments, offset) >= 0; // check block comments if (!isInLineComment) { if (!isInBlockComment) { isInBlockComment = StartsWithListMember (document, blockCommentStarts, offset) >= 0; } else { isInBlockComment = StartsWithListMember (document, blockCommentEnds, offset) < 0; } } } if (!isInBlockComment && !isInLineComment) { int i = StartsWithListMember (document, stringQuotes, offset); if (i >= 0) { if (curStringQuote >= 0) { if (curStringQuote == i) curStringQuote = -1; } else { curStringQuote = i; } } } char ch = document.GetCharAt (offset); switch (ch) { case '\n': case '\r': if (startsInLineComment) return -1; isInLineComment = false; break; default : if (ch == closingBracket) { if (!(isInLineComment || curStringQuote >= 0 || isInBlockComment)) --depth; } else if (ch == openBracket) { if (!(isInLineComment || curStringQuote >= 0 || isInBlockComment)) { ++depth; if (depth == 0) return offset; } } break; } offset++; } return -1; }
/// <summary> /// This method gets the line indentation. /// </summary> /// <param name="doc"> /// The <see cref="Document"/> the line belongs to. /// </param> /// <returns> /// The indentation of the line (all whitespace chars up to the first non ws char). /// </returns> public string GetIndentation (Document doc) { StringBuilder result = new StringBuilder (); int endOffset = this.Offset + this.EditableLength; for (int i = Offset; i < endOffset; i++) { char ch = doc.GetCharAt (i); if (ch != ' ' && ch != '\t') break; result.Append (ch); } return result.ToString (); }
// 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")); } } } }
static InsertionPoint GetInsertionPosition (Document doc, int line, int column) { int bodyEndOffset = doc.LocationToOffset (line, column) + 1; LineSegment curLine = doc.GetLine (line); if (curLine != null) { if (bodyEndOffset < curLine.Offset + curLine.EditableLength) return new InsertionPoint (new DocumentLocation (line, column + 1), NewLineInsertion.BlankLine, NewLineInsertion.BlankLine); } LineSegment nextLine = doc.GetLine (line + 1); int endOffset = nextLine != null ? nextLine.Offset : doc.Length; for (int i = bodyEndOffset; i < endOffset; i++) { char ch = doc.GetCharAt (i); if (!char.IsWhiteSpace (ch)) return new InsertionPoint (doc.OffsetToLocation (i), NewLineInsertion.BlankLine, NewLineInsertion.BlankLine); } if (nextLine == null) return new InsertionPoint (doc.OffsetToLocation (bodyEndOffset - 1), NewLineInsertion.BlankLine, NewLineInsertion.BlankLine); int oldLine = line; while (line < doc.LineCount && doc.GetLineIndent (line + 1).Length == doc.GetLine (line + 1).EditableLength) line++; NewLineInsertion insertBefore = NewLineInsertion.None; NewLineInsertion insertAfter = NewLineInsertion.None; int delta = line - oldLine; int lineNumber = line + 1; if (delta == 0) { insertBefore = NewLineInsertion.Eol; insertAfter = NewLineInsertion.BlankLine; } else if (delta == 1) { insertAfter = NewLineInsertion.BlankLine; } else if (delta == 2) { lineNumber--; insertAfter = NewLineInsertion.BlankLine; } else if (delta >= 3) { lineNumber -= 2; insertAfter = NewLineInsertion.None; } return new InsertionPoint (new DocumentLocation (lineNumber, doc.GetLineIndent (lineNumber).Length + 1), insertBefore, insertAfter); }
static bool IsEmptyLine(Document doc, LineSegment line) { for (int i = 0; i < line.EditableLength; i++) { char ch = doc.GetCharAt (line.Offset + i); if (!Char.IsWhiteSpace (ch)) return false; } return true; }