示例#1
0
        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);
        }
示例#2
0
        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);
        }