public IViewContent CreateContent (FilePath fileName, string mimeType, Project ownerProject) { IPlistEditingHandler handler = null; if (ownerProject != null && fileName != null) { var pf = ownerProject.GetProjectFile (fileName); var virtualPath = pf.ProjectVirtualPath; var handlers = Mono.Addins.AddinManager.GetExtensionObjects<IPlistEditingHandler> (EXT_PATH); foreach (var h in handlers) { if (h.CanHandle (ownerProject, virtualPath)) { handler = h; break; } } } return new PListEditorViewContent (handler, ownerProject); }
public void TransferFiles (IProgressMonitor monitor, Project sourceProject, FilePath sourcePath, Project targetProject, FilePath targetPath, bool removeFromSource, bool copyOnlyProjectFiles) { // When transfering directories, targetPath is the directory where the source // directory will be transfered, including the destination directory or file name. // For example, if sourcePath is /a1/a2/a3 and targetPath is /b1/b2, the // new folder or file will be /b1/b2 if (targetProject == null) throw new ArgumentNullException ("targetProject"); if (!targetPath.IsChildPathOf (targetProject.BaseDirectory)) throw new ArgumentException ("Invalid project folder: " + targetPath); if (sourceProject != null && !sourcePath.IsChildPathOf (sourceProject.BaseDirectory)) throw new ArgumentException ("Invalid project folder: " + sourcePath); if (copyOnlyProjectFiles && sourceProject == null) throw new ArgumentException ("A source project must be specified if copyOnlyProjectFiles is True"); bool sourceIsFolder = Directory.Exists (sourcePath); bool movingFolder = (removeFromSource && sourceIsFolder && ( !copyOnlyProjectFiles || IsDirectoryHierarchyEmpty (sourcePath))); // We need to remove all files + directories from the source project // but when dealing with the VCS addins we need to process only the // files so we do not create a 'file' in the VCS which corresponds // to a directory in the project and blow things up. List<ProjectFile> filesToRemove = null; List<ProjectFile> filesToMove = null; try { //get the real ProjectFiles if (sourceProject != null) { if (sourceIsFolder) { var virtualPath = sourcePath.ToRelative (sourceProject.BaseDirectory); // Grab all the child nodes of the folder we just dragged/dropped filesToRemove = sourceProject.Files.GetFilesInVirtualPath (virtualPath).ToList (); // Add the folder itself so we can remove it from the soruce project if its a Move operation var folder = sourceProject.Files.Where (f => f.ProjectVirtualPath == virtualPath).FirstOrDefault (); if (folder != null) filesToRemove.Add (folder); } else { filesToRemove = new List<ProjectFile> (); var pf = sourceProject.GetProjectFile (sourcePath); if (pf != null) filesToRemove.Add (pf); } } //get all the non-project files and create fake ProjectFiles if (!copyOnlyProjectFiles || sourceProject == null) { var col = new List<ProjectFile> (); GetAllFilesRecursive (sourcePath, col); if (sourceProject != null) { var names = new HashSet<string> (filesToRemove.Select (f => sourceProject.BaseDirectory.Combine (f.ProjectVirtualPath).ToString ())); foreach (var f in col) if (names.Add (f.Name)) filesToRemove.Add (f); } else { filesToRemove = col; } } } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Could not get any file from '{0}'.", sourcePath), ex); return; } // Strip out all the directories to leave us with just the files. filesToMove = filesToRemove.Where (f => f.Subtype != Subtype.Directory).ToList (); // If copying a single file, bring any grouped children along ProjectFile sourceParent = null; if (filesToMove.Count == 1 && sourceProject != null) { var pf = filesToMove[0]; if (pf != null && pf.HasChildren) foreach (ProjectFile child in pf.DependentChildren) filesToMove.Add (child); sourceParent = pf; } // Ensure that the destination folder is created, even if no files // are copied try { if (sourceIsFolder && !Directory.Exists (targetPath) && !movingFolder) FileService.CreateDirectory (targetPath); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Could not create directory '{0}'.", targetPath), ex); return; } // Transfer files // If moving a folder, do it all at once if (movingFolder) { try { FileService.MoveDirectory (sourcePath, targetPath); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("Directory '{0}' could not be moved.", sourcePath), ex); return; } } monitor.BeginTask (GettextCatalog.GetString ("Copying files..."), filesToMove.Count); ProjectFile targetParent = null; foreach (ProjectFile file in filesToMove) { bool fileIsLink = file.Project != null && file.IsLink; var sourceFile = fileIsLink ? file.Project.BaseDirectory.Combine (file.ProjectVirtualPath) : file.FilePath; FilePath newFile; if (sourceIsFolder) newFile = targetPath.Combine (sourceFile.ToRelative (sourcePath)); else if (sourceFile == sourcePath) newFile = targetPath; else if (sourceFile.ParentDirectory != targetPath.ParentDirectory) newFile = targetPath.ParentDirectory.Combine (sourceFile.ToRelative (sourcePath.ParentDirectory)); else newFile = GetTargetCopyName (sourceFile, false); if (!movingFolder && !fileIsLink) { try { FilePath fileDir = newFile.ParentDirectory; if (!Directory.Exists (fileDir) && !file.IsLink) FileService.CreateDirectory (fileDir); if (removeFromSource) FileService.MoveFile (sourceFile, newFile); else FileService.CopyFile (sourceFile, newFile); } catch (Exception ex) { monitor.ReportError (GettextCatalog.GetString ("File '{0}' could not be created.", newFile), ex); monitor.Step (1); continue; } } if (sourceProject != null) { if (fileIsLink) { var linkFile = (sourceProject == targetProject)? file : (ProjectFile) file.Clone (); if (movingFolder) { var abs = linkFile.Link.ToAbsolute (sourceProject.BaseDirectory); var relSrc = abs.ToRelative (sourcePath); var absTarg = relSrc.ToAbsolute (targetPath); linkFile.Link = absTarg.ToRelative (targetProject.BaseDirectory); } else { linkFile.Link = newFile.ToRelative (targetProject.BaseDirectory); } targetProject.Files.Add (linkFile); } else if (targetProject.Files.GetFile (newFile) == null) { ProjectFile projectFile = (ProjectFile) file.Clone (); projectFile.Name = newFile; if (targetParent == null) { if (file == sourceParent) targetParent = projectFile; } else if (sourceParent != null) { if (projectFile.DependsOn == sourceParent.Name) projectFile.DependsOn = targetParent.Name; } targetProject.Files.Add (projectFile); } } monitor.Step (1); } if (removeFromSource) { // Remove all files and directories under 'sourcePath' foreach (var v in filesToRemove) sourceProject.Files.Remove (v); } var pfolder = sourcePath.ParentDirectory; // If this was the last item in the folder, make sure we keep // a reference to the folder, so it is not deleted from the tree. if (removeFromSource && sourceProject != null && pfolder.CanonicalPath != sourceProject.BaseDirectory.CanonicalPath && pfolder.IsChildPathOf (sourceProject.BaseDirectory)) { pfolder = pfolder.ToRelative (sourceProject.BaseDirectory); if (!sourceProject.Files.GetFilesInVirtualPath (pfolder).Any ()) { var folderFile = new ProjectFile (sourceProject.BaseDirectory.Combine (pfolder)); folderFile.Subtype = Subtype.Directory; sourceProject.Files.Add (folderFile); } } monitor.EndTask (); }
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; }
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 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; }