void VisitComment(ParsedDocument result, SpecialsBag.Comment comment, string[] tagComments)
        {
            var cmt = new MonoDevelop.Ide.TypeSystem.Comment(comment.Content);

            cmt.CommentStartsLine = comment.StartsLine;
            switch (comment.CommentType)
            {
            case SpecialsBag.CommentType.Multi:
                cmt.CommentType = MonoDevelop.Ide.TypeSystem.CommentType.Block;
                cmt.OpenTag     = "/*";
                cmt.ClosingTag  = "*/";
                break;

            case SpecialsBag.CommentType.Single:
                cmt.CommentType = MonoDevelop.Ide.TypeSystem.CommentType.SingleLine;
                cmt.OpenTag     = "//";
                break;

            case SpecialsBag.CommentType.Documentation:
                cmt.CommentType     = MonoDevelop.Ide.TypeSystem.CommentType.Documentation;
                cmt.IsDocumentation = true;
                cmt.OpenTag         = "///";
                break;
            }
            cmt.Region = new DomRegion(comment.Line, comment.Col, comment.EndLine, comment.EndCol);
            result.Comments.Add(cmt);
            var trimmedContent = comment.Content.TrimStart();

            foreach (string tag in tagComments)
            {
                if (!trimmedContent.StartsWith(tag))
                {
                    continue;
                }
                result.Add(new Tag(tag, comment.Content, cmt.Region));
            }
        }
Beispiel #2
0
        public ParsedDocument Parse(bool storeAst, string file, TextReader content, Project prj = null)
        {
            if (!storeAst)
            {
                return(null);
            }

            ProjectFile pf      = null;
            var         modName = "";

            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);
                            modName = BuildModuleName(pf);
                            break;
                        }
                    }
                }
            }
            else if (prj.IsFileInProject(file))
            {
                pf      = prj.GetProjectFile(file);
                modName = BuildModuleName(pf);
            }

            // 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 = (ParsedDModule)LastParsedMod;

                // Build appropriate module name
                if (pf != null)
                {
                    d.DDom.ModuleName = BuildModuleName(pf);
                }

                LastParsedMod = null;
                return(d);
            }
            else
            {
                LastParsedMod = null;
            }

            var dprj = prj as DProject;

            // Remove obsolete ast from cache
            IAbstractSyntaxTree ast = null;

            if (dprj != null)
            {
                ast = dprj.LocalFileCache[modName];

                if (ast != null)
                {
                    dprj.LocalFileCache.Remove(ast);
                    dprj.LocalFileCache.UfcsCache.RemoveModuleItems(ast);
                    ast = null;
                }
            }

            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
            ast = parser.Parse();

            // Update project owner information / Build appropriate module name
            ast.ModuleName = modName;
            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);

                c.CommentType     = cm.CommentType.HasFlag(D_Parser.Parser.Comment.Type.Block) ? CommentType.Block : CommentType.SingleLine;
                c.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 - 2, cm.EndPosition.Line, cm.EndPosition.Column);

                doc.Comments.Add(c);

                // Enlist TODO/FIXME/HACK etc. stuff in the IDE's project task list
                foreach (var sct in CommentTag.SpecialCommentTags)
                {
                    if (c.Text.StartsWith(sct.Tag))
                    {
                        doc.Add(new Tag(sct.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

            return(doc);
        }
Beispiel #3
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 DProject;

            // Remove obsolete ast from cache
            DModule ast = null;
            if (dprj != null)
            {
                ast = dprj.LocalFileCache.GetModuleByFileName(file, prj.BaseDirectory) as DModule;

                if (ast != null)
                {
                    dprj.LocalFileCache.Remove(ast);
                    ast = null;
                }
            }

            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);

                c.CommentType = cm.CommentType.HasFlag(D_Parser.Parser.Comment.Type.Block) ? CommentType.Block : CommentType.SingleLine;
                c.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
                foreach (var sct in CommentTag.SpecialCommentTags)
                    if (c.Text.StartsWith(sct.Tag))
                    {
                        doc.Add(new Tag(sct.Tag, c.Text, c.Region));
                        break;
                    }
            }

            // Workaround for tags not being displayed
            if (prj != null)
            {
                var ctnt = TypeSystemService.GetProjectContentWrapper(prj);
                if (ctnt != null)
                {
                    var tags = ctnt.GetExtensionObject<ProjectCommentTags>();
                    if (tags != null)
                        tags.UpdateTags(prj, file, doc.TagComments);
                }
            }
            else
            {
                // 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
                var caches = new List<ParseCache>();

                foreach(var p in Ide.IdeApp.Workspace.GetAllProjects())
                    if (p is DProject)
                    {
                        dprj = p as DProject;
                        if (dprj.LocalIncludeCache.Remove(file))
                            caches.Add(dprj.LocalIncludeCache);
                        if (dprj.LocalFileCache.Remove(file))
                            caches.Add(dprj.LocalFileCache);
                    }

                foreach (var cmp in DCompilerService.Instance.Compilers)
                {
                    if (cmp.ParseCache.Remove(file))
                        caches.Add(cmp.ParseCache);
                }

                if(caches.Count > 0)
                {
                    var ctxt = Completion.DCodeCompletionSupport.CreateCurrentContext();
                    ctxt.CurrentContext.Set((IBlockNode)null);
                    foreach (var cch in caches)
                    {
                        //FIXME: Adjust the target module name and/or copy the ast head
                        cch.AddOrUpdate(ast);
                        cch.UfcsCache.CacheModuleMethods(ast, ctxt);
                    }
                }
            }
            #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

            return doc;
        }
Beispiel #4
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;
            }
            catch(System.Exception ex) {
                doc.ErrorList.Add(new Error(ErrorType.Error, ex.Message));
                return doc;
            }

            if(ast == null)
                return doc;

            // 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;
        }
Beispiel #5
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);
        }
		void ParseHtmlDocument (List<Error> errors)
		{
			var sb = new StringBuilder ();
			var spanList = new List<Span> ();
			comments = new List<Comment> ();

			Action<Span> action = (Span span) =>
			{
				if (span.Kind == SpanKind.Markup) {
					sb.Append (span.Content);
					spanList.Add (span);
				} else {
					for (int i = 0; i < span.Content.Length; i++) {
						char ch = span.Content[i];
						if (ch != '\r' && ch != '\n')
							sb.Append (' ');
						else
							sb.Append (ch);
					}
					if (span.Kind == SpanKind.Comment) {
						var comment = new Comment (span.Content)
						{
							OpenTag = "@*",
							ClosingTag = "*@",
							CommentType = CommentType.Block,
						};
						comment.Region = new DomRegion (
							currentDocument.OffsetToLocation (span.Start.AbsoluteIndex - comment.OpenTag.Length),
							currentDocument.OffsetToLocation (span.Start.AbsoluteIndex + span.Length + comment.ClosingTag.Length));
						comments.Add (comment);
					}
				}
			};

			editorParser.CurrentParseTree.Accept (new CallbackVisitor (action));

			var parser = new MonoDevelop.Xml.Parser.XmlParser (new WebFormsRootState (), true);

			try {
				parser.Parse (new StringReader (sb.ToString ()));
			} catch (Exception ex) {
				LoggingService.LogError ("Unhandled error parsing html in Razor document '" + (lastParsedFile ?? "") + "'", ex);
			}

			htmlParsedDocument = parser.Nodes.GetRoot ();
			errors.AddRange (parser.Errors);
		}
			public override void VisitTrivia (SyntaxTrivia trivia)
			{
				base.VisitTrivia (trivia);
				switch (trivia.Kind ()) {
				case SyntaxKind.MultiLineCommentTrivia:
				case SyntaxKind.MultiLineDocumentationCommentTrivia:
					{
						var cmt = new Comment (CropStart (trivia.ToString (), "/*"));
						cmt.CommentStartsLine = StartsLine(trivia);
						cmt.CommentType = CommentType.Block;
						cmt.OpenTag = "/*";
						cmt.ClosingTag = "*/";
						cmt.Region = GetRegion (trivia);
						Comments.Add (cmt);
						break;
					}
				case SyntaxKind.SingleLineCommentTrivia:
					{
						var cmt = new Comment (CropStart (trivia.ToString (), "//"));
						cmt.CommentStartsLine = StartsLine(trivia);
						cmt.CommentType = CommentType.SingleLine;
						cmt.OpenTag = "//";
						cmt.Region = GetRegion (trivia);
						Comments.Add (cmt);
						break;
					}
				case SyntaxKind.SingleLineDocumentationCommentTrivia:
					{
						var cmt = new Comment (CropStart (trivia.ToString (), "///"));
						cmt.CommentStartsLine = StartsLine(trivia);
						cmt.IsDocumentation = true;
						cmt.CommentType = CommentType.Documentation;
						cmt.OpenTag = "///";
						cmt.ClosingTag = "*/";
						cmt.Region = GetRegion (trivia);
						Comments.Add (cmt);
						break;
					}

				}

			}
Beispiel #8
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);
        }
Beispiel #9
0
        public ParsedDocument Parse(bool storeAst, string file, TextReader content, Project prj = null)
        {
            if (!storeAst)
                return null;

            // 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 = (ParsedDModule)LastParsedMod;
                if (prj!=null)
                {
                    var pf = prj.GetProjectFile(file);

                    // Build appropriate module name
                    if (pf != null)
                        d.DDom.ModuleName = BuildModuleName(pf);
                }
                LastParsedMod = null;
                return d;
            }
            else
                LastParsedMod = null;

            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
            var ast = parser.Parse();

            // Update project owner information
            if (prj is DProject)
            {
                var pf = prj.GetProjectFile(file);

                // Build appropriate module name
                if (pf != null)
                    ast.ModuleName = BuildModuleName(pf);
            }

            ast.FileName = file;
            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);

                c.CommentType = cm.CommentType.HasFlag(D_Parser.Parser.Comment.Type.Block) ? CommentType.Block : CommentType.SingleLine;
                c.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 - 2, cm.EndPosition.Line, cm.EndPosition.Column);

                doc.Comments.Add(c);

                // Enlist TODO/FIXME/HACK etc. stuff in the IDE's project task list
                foreach (var sct in CommentTag.SpecialCommentTags)
                    if (c.Text.StartsWith(sct.Tag))
                    {
                        doc.Add(new Tag(sct.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

            return doc;
        }
        public static IEnumerable <FoldingRegion> ToFolds(this IList <Comment> comments)
        {
            for (int i = 0; i < comments.Count; i++)
            {
                Comment comment = comments [i];

                if (comment.CommentType == CommentType.Block)
                {
                    int startOffset = 0;
                    if (comment.Region.BeginLine == comment.Region.EndLine)
                    {
                        continue;
                    }
                    while (startOffset < comment.Text.Length)
                    {
                        char ch = comment.Text [startOffset];
                        if (!char.IsWhiteSpace(ch) && ch != '*')
                        {
                            break;
                        }
                        startOffset++;
                    }
                    int endOffset = startOffset;
                    while (endOffset < comment.Text.Length)
                    {
                        char ch = comment.Text [endOffset];
                        if (ch == '\r' || ch == '\n' || ch == '*')
                        {
                            break;
                        }
                        endOffset++;
                    }

                    string txt;
                    if (endOffset > startOffset)
                    {
                        txt = "/* " + SubstrEllipsize(comment.Text, startOffset, endOffset - startOffset) + " */";
                    }
                    else
                    {
                        txt = "/* */";
                    }
                    yield return(new FoldingRegion(txt, comment.Region, FoldType.Comment));

                    continue;
                }

                if (!comment.CommentStartsLine)
                {
                    continue;
                }
                int j           = i;
                int curLine     = comment.Region.BeginLine - 1;
                var end         = comment.Region.End;
                var commentText = new StringBuilder();
                for (; j < comments.Count; j++)
                {
                    Comment curComment = comments [j];
                    if (curComment == null || !curComment.CommentStartsLine ||
                        curComment.CommentType != comment.CommentType ||
                        curLine + 1 != curComment.Region.BeginLine)
                    {
                        break;
                    }
                    commentText.Append(curComment.Text);
                    end     = curComment.Region.End;
                    curLine = curComment.Region.BeginLine;
                }

                if (j - i > 1)
                {
                    string txt;
                    if (comment.IsDocumentation)
                    {
                        txt = "/// ...";
                        string cmtText = commentText.ToString();
                        int    idx     = cmtText.IndexOf("<summary>");
                        if (idx >= 0)
                        {
                            int maxOffset = cmtText.IndexOf("</summary>");
                            while (maxOffset > 0 && cmtText[maxOffset - 1] == ' ')
                            {
                                maxOffset--;
                            }
                            if (maxOffset < 0)
                            {
                                maxOffset = cmtText.Length;
                            }
                            int startOffset = idx + "<summary>".Length;
                            while (startOffset < maxOffset)
                            {
                                char ch = cmtText [startOffset];
                                if (!char.IsWhiteSpace(ch) && ch != '/')
                                {
                                    break;
                                }
                                startOffset++;
                            }
                            int endOffset = startOffset;
                            while (endOffset < maxOffset)
                            {
                                char ch = cmtText [endOffset];
                                if (ch == '\r' || ch == '\n')
                                {
                                    break;
                                }
                                endOffset++;
                            }
                            if (endOffset > startOffset)
                            {
                                txt = "/// " + SubstrEllipsize(cmtText, startOffset, endOffset - startOffset);
                            }
                        }
                    }
                    else
                    {
                        txt = "// " + SubstrEllipsize(comment.Text, 0, comment.Text.Length);
                    }

                    yield return(new FoldingRegion(txt,
                                                   new DomRegion(comment.Region.Begin, end),
                                                   FoldType.Comment));

                    i = j - 1;
                }
            }
        }
 public void Add(Comment comment)
 {
     comments.Add(comment);
 }