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; }
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; }
// Handle unique deploy files, emits non-perconfig stuff, like targets for deploy files, // un/install commands void HandleDeployFile (DeployFileData data, string targetDeployVar, Project project, AutotoolsContext ctx) { DeployFile dfile = data.File; string dependencyDeployFile = null; //Dependency for the deployfile target if (dfile.ContainsPathReferences) { // Template file, copy to .in file string full_fname = Path.Combine (project.BaseDirectory, Path.GetFileName (dfile.RelativeTargetPath)); string fname = full_fname; string infname = fname + ".in"; if (File.Exists (infname) && project.IsFileInProject (infname)) { string datadir = Path.Combine (project.BaseDirectory, "data"); if (!Directory.Exists (datadir)) Directory.CreateDirectory (datadir); infname = Path.Combine (datadir, Path.GetFileName (dfile.RelativeTargetPath) + ".in"); } //Absolute path required File.Copy (dfile.SourcePath, infname, true); //Path relative to TargetCombine fname = FileService.NormalizeRelativePath ( FileService.AbsoluteToRelativePath (ctx.TargetSolution.BaseDirectory, full_fname)); infname = fname + ".in"; ctx.AddAutoconfFile (MakefileData.ToMakefilePath (fname)); ctx.AddGeneratedFile (full_fname + ".in"); //Path relative to project fname = FileService.NormalizeRelativePath ( FileService.AbsoluteToRelativePath (project.BaseDirectory, full_fname)); infname = fname + ".in"; extras.AppendFormat ("\\\n\t{0} ", MakefileData.ToMakefilePath (infname)); //dependencyDeployFile here should be filename relative to the project dependencyDeployFile = fname; } else { dependencyDeployFile = String.Format ("$({0}_SOURCE)", targetDeployVar); } builtFiles.Add (Path.GetFileName (dfile.RelativeTargetPath)); if (dfile.ContainsPathReferences) deployFileCopyTargets.AppendFormat ("$(eval $(call emit-deploy-wrapper,{0},{1}{2}))\n", targetDeployVar, MakefileData.ToMakefilePath (dependencyDeployFile), (dfile.FileAttributes & DeployFileAttributes.Executable) != 0 ? ",x" : String.Empty); else { // The emit-deploy-target macro copies the deployable file to the output directory. // This is not needed if the file is already there (e.g. for an .mdb file) if (Path.GetFullPath (dfile.SourcePath) != Path.GetFullPath (Path.Combine (data.Configuration.OutputDirectory, dfile.RelativeTargetPath))) deployFileCopyTargets.AppendFormat ("$(eval $(call emit-deploy-target,{0}))\n", targetDeployVar); } switch (dfile.TargetDirectoryID) { case TargetDirectory.Gac: // TODO break; default: string var; if (dfile.TargetDirectoryID != TargetDirectory.Binaries) { string ddir = FileService.NormalizeRelativePath (dfile.RelativeTargetPath.ParentDirectory.ToString().Trim ('/',' ')); if (ddir.Length > 0) ddir = "/" + ddir; var = ctx.GetDeployDirectoryVar (dfile.TargetDirectoryID + ddir); } else var = "BINARIES"; StringBuilder sb; if (!deployDirs.TryGetValue (var, out sb)) { sb = new StringBuilder (); deployDirs [var] = sb; } sb.AppendFormat ("\\\n\t$({0}) ", targetDeployVar); break; } if (!generateAutotools) { string installDir = Path.GetDirectoryName (ctx.DeployContext.GetResolvedPath (dfile.TargetDirectoryID, dfile.RelativeTargetPath)); //FIXME: temp installDir = TranslateDir (installDir); if (!installDirs.Contains (installDir)) { installTarget.AppendFormat ("\tmkdir -p '$(DESTDIR){0}'\n", installDir); installDirs.Add (installDir); } installTarget.AppendFormat ("\t$(call cp,$({0}),$(DESTDIR){1})\n", targetDeployVar, installDir); uninstallTarget.AppendFormat ("\t$(call rm,$({1}),$(DESTDIR){0})\n", installDir, targetDeployVar); } }