public override ParsedDocument Parse(bool storeAst, string file, TextReader content, Project prj = null) { if (!storeAst) { return(null); } ProjectFile pf = null; if (prj == null) { var sln = Ide.IdeApp.ProjectOperations.CurrentSelectedSolution; if (sln != null) { foreach (var proj in sln.GetAllProjects()) { if (proj.IsFileInProject(file)) { prj = proj; pf = proj.GetProjectFile(file); break; } } } } else if (prj.IsFileInProject(file)) { pf = prj.GetProjectFile(file); } // HACK(?) The folds are parsed before the document gets loaded // - so reuse the last parsed document to save time // -- What if multiple docs are opened? var d = LastParsedMod as ParsedDModule; if (d != null && d.FileName == file) { LastParsedMod = null; return(d); } else { LastParsedMod = null; } var dprj = prj as AbstractDProject; // Remove obsolete ast from cache if (file != null) { GlobalParseCache.RemoveModule(file); } DModule ast; var doc = new ParsedDModule(file); var parser = DParser.Create(content); // Also put attention on non-ddoc comments; These will be used to generate foldable comment regions then parser.Lexer.OnlyEnlistDDocComments = false; // Parse the code try { ast = parser.Parse(); } catch (TooManyErrorsException) { ast = parser.Document; } // Update project owner information / Build appropriate module name if (string.IsNullOrEmpty(ast.ModuleName)) { if (pf == null) { ast.ModuleName = file != null?Path.GetFileNameWithoutExtension(file) : string.Empty; } else { ast.ModuleName = BuildModuleName(pf); } } ast.FileName = file; // Assign new ast to the ParsedDDocument object doc.DDom = ast; // Add parser errors to the parser output foreach (var parserError in parser.ParseErrors) { doc.ErrorList.Add(new Error( ErrorType.Error, parserError.Message, parserError.Location.Line, parserError.Location.Column)); } #region Provide comment fold support by addin them to the IDE document object foreach (var cm in parser.Comments) { var c = new MonoDevelop.Ide.TypeSystem.Comment(cm.CommentText) { CommentStartsLine = cm.CommentStartsLine, CommentType = (cm.CommentType & D_Parser.Parser.Comment.Type.Block) != 0 ? CommentType.Block : CommentType.SingleLine, IsDocumentation = cm.CommentType.HasFlag(D_Parser.Parser.Comment.Type.Documentation), }; if (c.CommentType == CommentType.SingleLine) { if (c.IsDocumentation) { c.OpenTag = "///"; } else { c.OpenTag = "//"; } } else { if (c.IsDocumentation) { c.OpenTag = "/**"; c.ClosingTag = "*/"; } else { c.OpenTag = "/*"; c.ClosingTag = "*/"; } } c.Region = new DomRegion(cm.StartPosition.Line, cm.StartPosition.Column, cm.EndPosition.Line, cm.EndPosition.Column); doc.Comments.Add(c); // Enlist TODO/FIXME/HACK etc. stuff in the IDE's project task list for (int i = CommentTag.SpecialCommentTags.Count - 1; i >= 0; i--) { if (c.Text.StartsWith(CommentTag.SpecialCommentTags[i].Tag)) { doc.Add(new Tag(CommentTag.SpecialCommentTags[i].Tag, c.Text, c.Region)); break; } } } #endregion #region Serialize to NRefactory Dom structure /* * var cu = new CompilationUnit(file); * doc.CompilationUnit = cu; * * var global = new DomType(cu, ClassType.Class, * Modifiers.Public | Modifiers.Partial, * "(global)", * new DomLocation(), * ast.ModuleName, * new DomRegion()); * cu.Add(global); * * foreach (var n in ast) * { * var ch = ConvertDParserToDomNode(n, doc); * * if (ch is DomField || ch is DomMethod) * global.Add(ch as IMember); * else * cu.Add(ch as IType); * } */ #endregion if (prj != null) { // Workaround for tags not being displayed var ctnt = TypeSystemService.GetProjectContentWrapper(prj); if (ctnt != null) { var tags = ctnt.GetExtensionObject <ProjectCommentTags>(); if (tags != null) { tags.UpdateTags(prj, file, doc.TagComments); } } } return(doc); }
public override ParsedDocument Parse(bool storeAst, string file, TextReader content, Project prj = null) { if (!storeAst) { return(null); } ProjectFile pf = null; if (prj == null) { var sln = Ide.IdeApp.ProjectOperations.CurrentSelectedSolution; if (sln != null) { foreach (var proj in sln.GetAllProjects()) { if (proj.IsFileInProject(file)) { prj = proj; pf = proj.GetProjectFile(file); break; } } } } else if (prj.IsFileInProject(file)) { pf = prj.GetProjectFile(file); } // HACK(?) The folds are parsed before the document gets loaded // - so reuse the last parsed document to save time // -- What if multiple docs are opened? if (LastParsedMod is ParsedDModule && LastParsedMod.FileName == file) { var d = LastParsedMod as ParsedDModule; LastParsedMod = null; return(d); } else { LastParsedMod = null; } var dprj = prj as AbstractDProject; // Remove obsolete ast from cache GlobalParseCache.RemoveModule(file); DModule ast; var doc = new ParsedDModule(file); var parser = DParser.Create(content); // Also put attention on non-ddoc comments; These will be used to generate foldable comment regions then parser.Lexer.OnlyEnlistDDocComments = false; // Parse the code try { ast = parser.Parse(); } catch (TooManyErrorsException x) { ast = parser.Document; } // Update project owner information / Build appropriate module name if (string.IsNullOrEmpty(ast.ModuleName)) { if (pf == null) { ast.ModuleName = Path.GetFileNameWithoutExtension(file); } else { ast.ModuleName = BuildModuleName(pf); } } ast.FileName = file; // Assign new ast to the ParsedDDocument object doc.DDom = ast; // Add parser errors to the parser output foreach (var parserError in parser.ParseErrors) { doc.ErrorList.Add(new Error( ErrorType.Error, parserError.Message, parserError.Location.Line, parserError.Location.Column)); } #region Provide comment fold support by addin them to the IDE document object foreach (var cm in parser.TrackerVariables.Comments) { var c = new MonoDevelop.Ide.TypeSystem.Comment(cm.CommentText) { CommentStartsLine = cm.CommentStartsLine, CommentType = (cm.CommentType & D_Parser.Parser.Comment.Type.Block) != 0 ? CommentType.Block : CommentType.SingleLine, IsDocumentation = cm.CommentType.HasFlag(D_Parser.Parser.Comment.Type.Documentation), }; if (c.CommentType == CommentType.SingleLine) { if (c.IsDocumentation) { c.OpenTag = "///"; } else { c.OpenTag = "//"; } } else { if (c.IsDocumentation) { c.OpenTag = "/**"; c.ClosingTag = "*/"; } else { c.OpenTag = "/*"; c.ClosingTag = "*/"; } } c.Region = new DomRegion(cm.StartPosition.Line, cm.StartPosition.Column, cm.EndPosition.Line, cm.EndPosition.Column); doc.Comments.Add(c); // Enlist TODO/FIXME/HACK etc. stuff in the IDE's project task list for (int i = CommentTag.SpecialCommentTags.Count - 1; i >= 0; i--) { if (c.Text.StartsWith(CommentTag.SpecialCommentTags[i].Tag)) { doc.Add(new Tag(CommentTag.SpecialCommentTags[i].Tag, c.Text, c.Region)); break; } } } #endregion #region Serialize to NRefactory Dom structure /* * var cu = new CompilationUnit(file); * doc.CompilationUnit = cu; * * var global = new DomType(cu, ClassType.Class, * Modifiers.Public | Modifiers.Partial, * "(global)", * new DomLocation(), * ast.ModuleName, * new DomRegion()); * cu.Add(global); * * foreach (var n in ast) * { * var ch = ConvertDParserToDomNode(n, doc); * * if (ch is DomField || ch is DomMethod) * global.Add(ch as IMember); * else * cu.Add(ch as IType); * } */ #endregion if (prj != null) { // Workaround for tags not being displayed var ctnt = TypeSystemService.GetProjectContentWrapper(prj); if (ctnt != null) { var tags = ctnt.GetExtensionObject <ProjectCommentTags>(); if (tags != null) { tags.UpdateTags(prj, file, doc.TagComments); } } } // Update UFCS ModulePackage pack; if ((pack = GlobalParseCache.GetPackage(ast, false)) != null && (pack = pack.Root) != null) { // If the file is not associated with any project, // check if the file is located in an imported/included directory // and update the respective cache. // Note: ParseCache.Remove() also affects the Ufcs cache, // but when adding it again, the UfcsCache has to be updated manually ParseCacheView pcw; bool containsPack = false; if (prj != null) { pcw = dprj.ParseCache; containsPack = true; } else { // Find out which compiler environment fits most pcw = null; foreach (var cmp in DCompilerService.Instance.Compilers) { pcw = cmp.GenParseCacheView(); foreach (var r in pack as IEnumerable <ModulePackage> ) { if (r == pack) { containsPack = true; break; } } if (containsPack) { break; } } } if (containsPack) { (pack as RootPackage).UfcsCache.CacheModuleMethods(ast, new ResolutionContext(pcw, null, ast)); } } return(doc); }