// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Core; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.TypeSystem; using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor.Search; using ICSharpCode.SharpDevelop.Parser; using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Refactoring; namespace CSharpBinding.Parser { public class TParser : IParser { ///IParser Interface string[] lexerTags; public string[] LexerTags { get { return lexerTags; } set { lexerTags = value; } } public bool CanParse(string fileName) { return Path.GetExtension(fileName).Equals(".CS", StringComparison.OrdinalIgnoreCase); } /* void RetrieveRegions(ICompilationUnit cu, ICSharpCode.NRefactory.Parser.SpecialTracker tracker) { for (int i = 0; i < tracker.CurrentSpecials.Count; ++i) { ICSharpCode.NRefactory.PreprocessingDirective directive = tracker.CurrentSpecials[i] as ICSharpCode.NRefactory.PreprocessingDirective; if (directive != null) { if (directive.Cmd == "#region") { int deep = 1; for (int j = i + 1; j < tracker.CurrentSpecials.Count; ++j) { ICSharpCode.NRefactory.PreprocessingDirective nextDirective = tracker.CurrentSpecials[j] as ICSharpCode.NRefactory.PreprocessingDirective; if (nextDirective != null) { switch (nextDirective.Cmd) { case "#region": ++deep; break; case "#endregion": --deep; if (deep == 0) { cu.FoldingRegions.Add(new FoldingRegion(directive.Arg.Trim(), DomRegion.FromLocation(directive.StartPosition, nextDirective.EndPosition))); goto end; } break; } } } end: ; } } } } */ public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested) { CSharpParser parser = new CSharpParser(); parser.GenerateTypeSystemMode = !fullParseInformationRequested; CompilationUnit cu = parser.Parse(fileContent.CreateReader(), fileName); CSharpParsedFile file = cu.ToTypeSystem(); ParseInformation parseInfo; if (fullParseInformationRequested) parseInfo = new CSharpFullParseInformation(file, cu); else parseInfo = new ParseInformation(file, fullParseInformationRequested); AddCommentTags(cu, parseInfo.TagComments, fileContent); return parseInfo; } void AddCommentTags(CompilationUnit cu, IList tagComments, ITextSource fileContent) { ReadOnlyDocument document = null; foreach (var comment in cu.Descendants.OfType().Where(c => c.CommentType != CommentType.InactiveCode)) { int matchLength; int index = IndexOfAny(comment.Content, lexerTags, 0, out matchLength); if (index > -1) { if (document == null) document = new ReadOnlyDocument(fileContent); int startOffset = document.GetOffset(comment.StartLocation); int commentSignLength = comment.CommentType == CommentType.Documentation || comment.CommentType == CommentType.MultiLineDocumentation ? 3 : 2; int commentEndSignLength = comment.CommentType == CommentType.MultiLine || comment.CommentType == CommentType.MultiLineDocumentation ? 2 : 0; do { int absoluteOffset = startOffset + index + commentSignLength; var startLocation = document.GetLocation(absoluteOffset); int endOffset = Math.Min(document.GetLineByNumber(startLocation.Line).EndOffset, document.GetOffset(comment.EndLocation) - commentEndSignLength); string content = document.GetText(absoluteOffset, endOffset - absoluteOffset); tagComments.Add(new TagComment(content.Substring(0, matchLength), new DomRegion(cu.FileName, startLocation.Line, startLocation.Column), content.Substring(matchLength))); index = IndexOfAny(comment.Content, lexerTags, endOffset - startOffset - commentSignLength, out matchLength); } while (index > -1); } } } static int IndexOfAny(string haystack, string[] needles, int startIndex, out int matchLength) { if (haystack == null) throw new ArgumentNullException("haystack"); if (needles == null) throw new ArgumentNullException("needles"); int index = -1; matchLength = 0; foreach (var needle in needles) { int i = haystack.IndexOf(needle, startIndex, StringComparison.Ordinal); if (i != -1 && (index == -1 || index > i)) { index = i; matchLength = needle.Length; } } return index; } public ResolveResult Resolve(ParseInformation parseInfo, TextLocation location, ICompilation compilation, CancellationToken cancellationToken) { var csParseInfo = parseInfo as CSharpFullParseInformation; if (csParseInfo == null) throw new ArgumentException("Parse info does not have CompilationUnit"); return ResolveAtLocation.Resolve(compilation, csParseInfo.ParsedFile, csParseInfo.CompilationUnit, location, cancellationToken); } public void FindLocalReferences(ParseInformation parseInfo, ITextSource fileContent, IVariable variable, ICompilation compilation, Action callback, CancellationToken cancellationToken) { var csParseInfo = parseInfo as CSharpFullParseInformation; if (csParseInfo == null) throw new ArgumentException("Parse info does not have CompilationUnit"); ReadOnlyDocument document = null; DocumentHighlighter highlighter = null; new FindReferences().FindLocalReferences( variable, csParseInfo.ParsedFile, csParseInfo.CompilationUnit, compilation, delegate (AstNode node, ResolveResult result) { if (document == null) { document = new ReadOnlyDocument(fileContent); var highlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(csParseInfo.FileName)); if (highlighting != null) highlighter = new DocumentHighlighter(document, highlighting.MainRuleSet); else highlighter = null; } var region = new DomRegion(parseInfo.FileName, node.StartLocation, node.EndLocation); int offset = document.GetOffset(node.StartLocation); int length = document.GetOffset(node.EndLocation) - offset; var builder = SearchResultsPad.CreateInlineBuilder(node.StartLocation, node.EndLocation, document, highlighter); callback(new Reference(region, result, offset, length, builder)); }, cancellationToken); } } }