diff options
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs')
-rw-r--r-- | main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs | 531 |
1 files changed, 277 insertions, 254 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs index eff3218cc9..c96d9fb360 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui/Document.cs @@ -47,23 +47,25 @@ using MonoDevelop.Ide.Extensions; using System.Linq; using System.Threading; using MonoDevelop.Ide.TypeSystem; -using ICSharpCode.NRefactory; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; using System.Text; using System.Collections.ObjectModel; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Options; +using MonoDevelop.Ide.Editor; +using MonoDevelop.Ide.Editor.Highlighting; +using MonoDevelop.Core.Text; namespace MonoDevelop.Ide.Gui { - public class Document : ICSharpCode.NRefactory.AbstractAnnotatable + + public class Document : DocumentContext { internal object MemoryProbe = Counters.DocumentsInMemory.CreateMemoryProbe (); IWorkbenchWindow window; - TextEditorExtension editorExtension; ParsedDocument parsedDocument; - IProjectContent singleFileContext; - Mono.TextEditor.ITextEditorDataProvider provider = null; + FilePath analysisDocumentFileName; + Microsoft.CodeAnalysis.DocumentId analysisDocument; const int ParseDelay = 600; @@ -75,12 +77,20 @@ namespace MonoDevelop.Ide.Gui get; set; } - - public TextEditorExtension EditorExtension { - get { return this.editorExtension; } + + /// <summary> + /// Returns the roslyn document for this document. This may return <c>null</c> if it's no compileable document. + /// Even if it's a C# file. + /// </summary> + public override Microsoft.CodeAnalysis.Document AnalysisDocument { + get { + if (analysisDocument == null) + return null; + return TypeSystemService.GetCodeAnalysisDocument (analysisDocument); + } } - public T GetContent<T> () where T : class + public override T GetContent<T> () { if (window == null) return null; @@ -97,39 +107,30 @@ namespace MonoDevelop.Ide.Gui return ret; } - //no, so look through the TexteditorExtensions as well - TextEditorExtension nextExtension = editorExtension; - while (nextExtension != null) { - if (typeof(T).IsAssignableFrom (nextExtension.GetType ())) - return nextExtension as T; - nextExtension = nextExtension.Next as TextEditorExtension; + //If we didn't find in ActiveView or ViewContent... Try in SubViews + foreach (var subView in window.SubViewContents) { + foreach (var cnt in subView.GetContents<T> ()) { + return cnt; + } } + return null; } - public IEnumerable<T> GetContents<T> () where T : class + public override IEnumerable<T> GetContents<T> () { - //check whether the ViewContent can return the type directly - T ret = (T) Window.ActiveViewContent.GetContent (typeof(T)); - if (ret != null) - yield return ret; - - //check the primary viewcontent - //not sure if this is the right thing to do, but things depend on this behaviour - if (Window.ViewContent != Window.ActiveViewContent) { - ret = (T) Window.ViewContent.GetContent (typeof(T)); - if (ret != null) - yield return ret; + foreach (var cnt in window.ViewContent.GetContents<T> ()) { + yield return cnt; } - - //no, so look through the TexteditorExtensions as well - TextEditorExtension nextExtension = editorExtension; - while (nextExtension != null) { - if (typeof(T).IsAssignableFrom (nextExtension.GetType ())) - yield return nextExtension as T; - nextExtension = nextExtension.Next as TextEditorExtension; + + foreach (var subView in window.SubViewContents) { + foreach (var cnt in subView.GetContents<T> ()) { + yield return cnt; + } } } + + static Document () { if (IdeApp.Workbench != null) { @@ -155,6 +156,19 @@ namespace MonoDevelop.Ide.Gui if (window.ViewContent.Project != null) window.ViewContent.Project.Modified += HandleProjectModified; window.ViewsChanged += HandleViewsChanged; + window.ViewContent.ContentNameChanged += delegate { + analysisDocument = null; + }; + MonoDevelopWorkspace.LoadingFinished += TypeSystemService_WorkspaceItemLoaded; + } + + void TypeSystemService_WorkspaceItemLoaded (object sender, EventArgs e) + { + if (adhocProject == null) + analysisDocument = null; + EnsureAnalysisDocumentIsOpen (); + if (analysisDocument != null) + StartReparseThread (); } /* void UpdateRegisteredDom (object sender, ProjectDomEventArgs e) @@ -182,13 +196,12 @@ namespace MonoDevelop.Ide.Gui get { return !Window.ViewContent.IsViewOnly && (Window.ViewContent.ContentName == null || Window.ViewContent.IsDirty); } set { Window.ViewContent.IsDirty = value; } } - - public bool HasProject { - get { return Window != null ? Window.ViewContent.Project != null : false; } - } - - public Project Project { - get { return Window != null ? Window.ViewContent.Project : null; } + + FilePath adHocFile; + Project adhocProject; + + public override Project Project { + get { return (Window != null ? Window.ViewContent.Project : null); } /* set { Window.ViewContent.Project = value; if (value != null) @@ -199,7 +212,7 @@ namespace MonoDevelop.Ide.Gui }*/ } - public bool IsCompileableInProject { + public override bool IsCompileableInProject { get { var project = Project; if (project == null) @@ -220,19 +233,15 @@ namespace MonoDevelop.Ide.Gui } } - public IProjectContent ProjectContent { - get { - return Project != null ? TypeSystemService.GetProjectContext (Project) : GetProjectContext (); - } - } - - public virtual ICompilation Compilation { - get { - return Project != null ? TypeSystemService.GetCompilation (Project) : GetProjectContext ().CreateCompilation (); - } + public Task<Microsoft.CodeAnalysis.Compilation> GetCompilationAsync(CancellationToken cancellationToken = default(CancellationToken)) + { + var project = TypeSystemService.GetCodeAnalysisProject (Project ?? adhocProject); + if (project == null) + return new Task<Microsoft.CodeAnalysis.Compilation> (() => null); + return project.GetCompilationAsync (cancellationToken); } - - public virtual ParsedDocument ParsedDocument { + + public override ParsedDocument ParsedDocument { get { return parsedDocument; } @@ -300,21 +309,16 @@ namespace MonoDevelop.Ide.Gui return new DocumentView (this, content); } - public string Name { + public override string Name { get { IViewContent view = Window.ViewContent; return view.IsUntitled ? view.UntitledName : view.ContentName; } } - public Mono.TextEditor.TextEditorData Editor { + public TextEditor Editor { get { - if (provider == null) { - provider = GetContent <Mono.TextEditor.ITextEditorDataProvider> (); - if (provider == null) - return null; - } - return provider.GetTextEditorData (); + return GetContent <TextEditor> (); } } @@ -378,21 +382,21 @@ namespace MonoDevelop.Ide.Gui // Set the file time of the current document after the file time of the written file, to prevent double file updates. // Note that the parsed document may be overwritten by a background thread to a more recent one. var doc = parsedDocument; - if (doc != null && doc.ParsedFile != null) { + if (doc != null) { string fileName = Window.ViewContent.ContentName; try { // filename could be null if the user cancelled SaveAs and this is a new & unsaved file if (fileName != null) - doc.ParsedFile.LastWriteTime = File.GetLastWriteTimeUtc (fileName); + doc.LastWriteTimeUtc = File.GetLastWriteTimeUtc (fileName); } catch (Exception e) { - doc.ParsedFile.LastWriteTime = DateTime.UtcNow; + doc.LastWriteTimeUtc = DateTime.UtcNow; LoggingService.LogWarning ("Exception while getting the write time from " + fileName, e); } } TypeSystemService.TrackFileChanges = true; } } - + public void SaveAs () { SaveAs (null); @@ -406,11 +410,11 @@ namespace MonoDevelop.Ide.Gui Encoding encoding = null; - IEncodedTextContent tbuffer = GetContent <IEncodedTextContent> (); + var tbuffer = GetContent <ITextSource> (); if (tbuffer != null) { - encoding = tbuffer.SourceEncoding; + encoding = tbuffer.Encoding; if (encoding == null) - encoding = Encoding.Default; + encoding = Encoding.UTF8; } if (filename == null) { @@ -446,16 +450,13 @@ namespace MonoDevelop.Ide.Gui // save backup first if ((bool)PropertyService.Get ("SharpDevelop.CreateBackupCopy", false)) { if (tbuffer != null && encoding != null) - tbuffer.Save (filename + "~", encoding); + TextFileUtility.WriteText (filename + "~", tbuffer.Text, encoding, tbuffer.UseBOM); else - Window.ViewContent.Save (filename + "~"); + Window.ViewContent.Save (new FileSaveInformation (filename + "~", encoding)); } TypeSystemService.RemoveSkippedfile (FileName); // do actual save - if (tbuffer != null && encoding != null) - tbuffer.Save (filename, encoding); - else - Window.ViewContent.Save (filename); + Window.ViewContent.Save (new FileSaveInformation (filename + "~", encoding)); FileService.NotifyFileChanged (filename); DesktopService.RecentFiles.AddFile (filename, (Project)null); @@ -468,12 +469,11 @@ namespace MonoDevelop.Ide.Gui { return ((SdiWorkspaceWindow)Window).CloseWindow (false, true); } - - void OnSaved (EventArgs args) + + protected override void OnSaved (EventArgs e) { IdeApp.Workbench.SaveFileStatus (); - if (Saved != null) - Saved (this, args); + base.OnSaved (e); } public void CancelParseTimeout () @@ -518,8 +518,14 @@ namespace MonoDevelop.Ide.Gui internal void DisposeDocument () { - DetachExtensionChain (); - RemoveAnnotations (typeof(System.Object)); + if (analysisDocument != null) { + TypeSystemService.InformDocumentClose (analysisDocument, FileName); + analysisDocument = null; + } + UnloadAdhocProject (); + if (Editor != null) { + Editor.Dispose (); + } if (window is SdiWorkspaceWindow) ((SdiWorkspaceWindow)window).DetachFromPathedDocument (); window.Closed -= OnClosed; @@ -531,11 +537,12 @@ namespace MonoDevelop.Ide.Gui if (window.ViewContent.Project != null) window.ViewContent.Project.Modified -= HandleProjectModified; window.ViewsChanged += HandleViewsChanged; + TypeSystemService.Workspace.WorkspaceChanged -= HandleWorkspaceChanged; + MonoDevelopWorkspace.LoadingFinished -= TypeSystemService_WorkspaceItemLoaded; + window = null; parsedDocument = null; - singleFileContext = null; - provider = null; views = null; viewsRO = null; } @@ -587,84 +594,44 @@ namespace MonoDevelop.Ide.Gui void InitializeExtensionChain () { - DetachExtensionChain (); - var editor = GetContent<IExtensibleTextEditor> (); - - ExtensionNodeList extensions = window.ExtensionContext.GetExtensionNodes ("/MonoDevelop/Ide/TextEditorExtensions", typeof(TextEditorExtensionNode)); - editorExtension = null; - TextEditorExtension last = null; - var mimetypeChain = DesktopService.GetMimeTypeInheritanceChainForFile (FileName).ToArray (); - foreach (TextEditorExtensionNode extNode in extensions) { - if (!extNode.Supports (FileName, mimetypeChain)) - continue; - TextEditorExtension ext; - try { - ext = (TextEditorExtension)extNode.CreateInstance (); - } catch (Exception e) { - LoggingService.LogError ("Error while creating text editor extension :" + extNode.Id + "(" + extNode.Type +")", e); - continue; - } - if (ext.ExtendsEditor (this, editor)) { - if (last != null) { - ext.Next = last.Next; - last.Next = ext; - last = ext; - } else { - editorExtension = last = ext; - last.Next = editor.AttachExtension (editorExtension); - } - ext.Initialize (this); - } - } + Editor.InitializeExtensionChain (this); + if (window is SdiWorkspaceWindow) ((SdiWorkspaceWindow)window).AttachToPathedDocument (GetContent<MonoDevelop.Ide.Gui.Content.IPathedDocument> ()); - } - void DetachExtensionChain () - { - while (editorExtension != null) { - try { - editorExtension.Dispose (); - } catch (Exception ex) { - LoggingService.LogError ("Exception while disposing extension:" + editorExtension, ex); - } - editorExtension = editorExtension.Next as TextEditorExtension; - } - editorExtension = null; } - void InitializeEditor (IExtensibleTextEditor editor) + void InitializeEditor () { - Editor.Document.TextReplaced += (o, a) => { + Editor.TextChanged += (o, a) => { if (parsedDocument != null) parsedDocument.IsInvalid = true; - if (Editor.Document.IsInAtomicUndo) { + if (Editor.IsInAtomicUndo) { wasEdited = true; } else { StartReparseThread (); } }; - Editor.Document.BeginUndo += delegate { + Editor.BeginAtomicUndoOperation += delegate { wasEdited = false; }; - Editor.Document.EndUndo += delegate { + Editor.EndAtomicUndoOperation += delegate { if (wasEdited) StartReparseThread (); }; - Editor.Document.Undone += (o, a) => StartReparseThread (); - Editor.Document.Redone += (o, a) => StartReparseThread (); +// Editor.Undone += (o, a) => StartReparseThread (); +// Editor.Redone += (o, a) => StartReparseThread (); InitializeExtensionChain (); } internal void OnDocumentAttached () { - IExtensibleTextEditor editor = GetContent<IExtensibleTextEditor> (); - if (editor != null) { - InitializeEditor (editor); + if (Editor != null) { + InitializeEditor (); RunWhenLoaded (delegate { ListenToProjectLoad (Project); }); } @@ -680,24 +647,25 @@ namespace MonoDevelop.Ide.Gui public void RunWhenLoaded (System.Action action) { var e = Editor; - if (e == null || e.Document == null) { + if (e == null) { action (); return; } - e.Document.RunWhenLoaded (action); + e.RunWhenLoaded (action); } - public void AttachToProject (Project project) + public override void AttachToProject (Project project) { SetProject (project); } - TypeSystemService.ProjectContentWrapper currentWrapper; internal void SetProject (Project project) { if (Window == null || Window.ViewContent == null || Window.ViewContent.Project == project) return; - DetachExtensionChain (); + UnloadAdhocProject (); + if (adhocProject == null) + analysisDocument = null; ISupportsProjectReload pr = GetContent<ISupportsProjectReload> (); if (pr != null) { // Unsubscribe project events @@ -709,22 +677,19 @@ namespace MonoDevelop.Ide.Gui if (project != null) project.Modified += HandleProjectModified; InitializeExtensionChain (); - + TypeSystemService.Workspace.WorkspaceChanged += HandleWorkspaceChanged; ListenToProjectLoad (project); } - void ListenToProjectLoad (Project project) + void HandleWorkspaceChanged (object sender, Microsoft.CodeAnalysis.WorkspaceChangeEventArgs e) { - if (currentWrapper != null) { - currentWrapper.Loaded -= HandleInLoadChanged; - currentWrapper = null; - } - if (project != null) { - var wrapper = TypeSystemService.GetProjectContentWrapper (project); - wrapper.Loaded += HandleInLoadChanged; - currentWrapper = wrapper; - currentWrapper.RequestLoad (); + if (e.Kind == Microsoft.CodeAnalysis.WorkspaceChangeKind.DocumentChanged && e.DocumentId == analysisDocument) { + OnDocumentParsed (EventArgs.Empty); } + } + + void ListenToProjectLoad (Project project) + { StartReparseThread (); } @@ -746,18 +711,30 @@ namespace MonoDevelop.Ide.Gui /// <returns> /// A <see cref="ParsedDocument"/> that contains the current dom. /// </returns> - public ParsedDocument UpdateParseDocument () + public override ParsedDocument UpdateParseDocument () { try { + EnsureAnalysisDocumentIsOpen (); string currentParseFile = FileName; var editor = Editor; if (editor == null || string.IsNullOrEmpty (currentParseFile)) return null; TypeSystemService.AddSkippedFile (currentParseFile); - string currentParseText = editor.Text; - this.parsedDocument = TypeSystemService.ParseFile (Project, currentParseFile, editor.Document.MimeType, currentParseText); - if (Project == null && this.parsedDocument != null) { - singleFileContext = GetProjectContext ().AddOrUpdateFiles (parsedDocument.ParsedFile); + var currentParseText = editor.CreateDocumentSnapshot (); + CancelOldParsing(); + var project = Project ?? adhocProject; + if (project != null && TypeSystemService.CanParseProjections (project, Editor.MimeType, FileName)) { + var task = TypeSystemService.ParseProjection (project, currentParseFile, editor.MimeType, currentParseText); + if (task.Result != null) { + var p = task.Result; + this.parsedDocument = p.ParsedDocument; + var projections = p.Projections; + foreach (var p2 in projections) + p2.CreateProjectedEditor (this); + Editor.SetOrUpdateProjections (this, projections, p.DisabledProjectionFeatures); + } + } else { + this.parsedDocument = TypeSystemService.ParseFile (project, currentParseFile, editor.MimeType, currentParseText).Result ?? this.parsedDocument; } } finally { @@ -765,89 +742,136 @@ namespace MonoDevelop.Ide.Gui } return this.parsedDocument; } + + uint parseTimeout = 0; - static readonly Lazy<IUnresolvedAssembly> mscorlib = new Lazy<IUnresolvedAssembly> ( () => new IkvmLoader ().LoadAssemblyFile (typeof (object).Assembly.Location)); - static readonly Lazy<IUnresolvedAssembly> systemCore = new Lazy<IUnresolvedAssembly>( () => new IkvmLoader ().LoadAssemblyFile (typeof (System.Linq.Enumerable).Assembly.Location)); - static readonly Lazy<IUnresolvedAssembly> system = new Lazy<IUnresolvedAssembly>( () => new IkvmLoader ().LoadAssemblyFile (typeof (System.Uri).Assembly.Location)); - - static IUnresolvedAssembly Mscorlib { get { return mscorlib.Value; } } - static IUnresolvedAssembly SystemCore { get { return systemCore.Value; } } - static IUnresolvedAssembly System { get { return system.Value; } } - - public bool IsProjectContextInUpdate { - get { - if (currentWrapper == null) - return false; - return !currentWrapper.IsLoaded; + void EnsureAnalysisDocumentIsOpen () + { + if (analysisDocument != null) + return; + if (Editor == null) { + analysisDocument = null; + return; + } + analysisDocumentFileName = FileName; + if (Project != null) { + RoslynWorkspace = TypeSystemService.GetWorkspace (this.Project.ParentSolution); + analysisDocument = TypeSystemService.GetDocumentId (this.Project, this.FileName); + if (analysisDocument != null) { + TypeSystemService.InformDocumentOpen (analysisDocument, Editor); + } + } else { + lock (adhocProjectLock) { + if (adhocProject != null) { + return; + } + if (Editor != null && Editor.MimeType == "text/x-csharp") { + var newProject = new DotNetAssemblyProject (Microsoft.CodeAnalysis.LanguageNames.CSharp); + this.adhocProject = newProject; + + newProject.Name = "InvisibleProject"; + newProject.References.Add (new ProjectReference (ReferenceType.Package, "mscorlib")); + newProject.References.Add (new ProjectReference (ReferenceType.Package, "System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")); + newProject.References.Add (new ProjectReference (ReferenceType.Package, "System.Core")); + + newProject.FileName = "test.csproj"; + adHocFile = Platform.IsWindows ? "C:\\a.cs" : "/a.cs"; + newProject.Files.Add (new ProjectFile (adHocFile, BuildAction.Compile)); + + var solution = new Solution (); + solution.AddConfiguration ("", true); + solution.DefaultSolutionFolder.AddItem (newProject); + using (var monitor = new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor ()) + RoslynWorkspace = TypeSystemService.Load (solution, monitor, false); + analysisDocument = TypeSystemService.GetDocumentId (RoslynWorkspace, adhocProject, adHocFile); + TypeSystemService.InformDocumentOpen (RoslynWorkspace, analysisDocument, Editor); + } + } } } + object adhocProjectLock = new object(); - public virtual IProjectContent GetProjectContext () + void UnloadAdhocProject () { - if (Project == null) { - if (singleFileContext == null) { - singleFileContext = new ICSharpCode.NRefactory.CSharp.CSharpProjectContent (); - singleFileContext = singleFileContext.AddAssemblyReferences (new [] { Mscorlib, System, SystemCore }); - } - if (parsedDocument != null) - return singleFileContext.AddOrUpdateFiles (parsedDocument.ParsedFile); - return singleFileContext; + lock (adhocProjectLock) { + if (adhocProject == null) + return; + TypeSystemService.Unload (adhocProject.ParentSolution.ParentWorkspace); + adhocProject = null; } - - return TypeSystemService.GetProjectContext (Project); } - - uint parseTimeout = 0; + object reparseLock = new object(); - internal void StartReparseThread () + CancellationTokenSource parseTokenSource = new CancellationTokenSource(); + int reparseQueue; + void CancelOldParsing() { - lock (reparseLock) { - if (currentWrapper != null) - currentWrapper.EnsureReferencesAreLoaded (); + parseTokenSource.Cancel (); + parseTokenSource = new CancellationTokenSource (); + } + internal void StartReparseThread () + { + string currentParseFile = adhocProject != null ? adHocFile : FileName; + if (string.IsNullOrEmpty (currentParseFile)) + return; + Interlocked.Increment (ref reparseQueue); + Application.Invoke (delegate { + if (Interlocked.Decrement (ref reparseQueue) != 0) { + return; + } // Don't directly parse the document because doing it at every key press is // very inefficient. Do it after a small delay instead, so several changes can // be parsed at the same time. - string currentParseFile = FileName; - if (string.IsNullOrEmpty (currentParseFile)) - return; + EnsureAnalysisDocumentIsOpen (); CancelParseTimeout (); - if (IsProjectContextInUpdate) { - return; - } - parseTimeout = GLib.Timeout.Add (ParseDelay, delegate { - var editor = Editor; - if (editor == null || IsProjectContextInUpdate) { - parseTimeout = 0; - return false; - } - string currentParseText = editor.Text; - string mimeType = editor.Document.MimeType; - ThreadPool.QueueUserWorkItem (delegate { - if (IsProjectContextInUpdate) { - return; - } - TypeSystemService.AddSkippedFile (currentParseFile); - var currentParsedDocument = TypeSystemService.ParseFile (Project, currentParseFile, mimeType, currentParseText); - Application.Invoke (delegate { - // this may be called after the document has closed, in that case the OnDocumentParsed event shouldn't be invoked. - if (isClosed) + var currentParseText = Editor.CreateSnapshot (); + string mimeType = Editor.MimeType; + CancelOldParsing (); + var token = parseTokenSource.Token; + var project = Project ?? adhocProject; + ThreadPool.QueueUserWorkItem (delegate { + TypeSystemService.AddSkippedFile (currentParseFile); + if (project != null && TypeSystemService.CanParseProjections (project, mimeType, currentParseFile)) { + TypeSystemService.ParseProjection (project, currentParseFile, mimeType, currentParseText, token).ContinueWith (task => { + if (token.IsCancellationRequested) return; - this.parsedDocument = currentParsedDocument; - OnDocumentParsed (EventArgs.Empty); - }); - }); + Application.Invoke (delegate { + // this may be called after the document has closed, in that case the OnDocumentParsed event shouldn't be invoked. + var taskResult = task.Result; + if (isClosed || taskResult == null || token.IsCancellationRequested) + return; + this.parsedDocument = taskResult.ParsedDocument; + var projections = taskResult.Projections; + foreach (var p2 in projections) + p2.CreateProjectedEditor (this); + Editor.SetOrUpdateProjections (this, projections, taskResult.DisabledProjectionFeatures); + OnDocumentParsed (EventArgs.Empty); + }); + }, TaskContinuationOptions.OnlyOnRanToCompletion); + } else { + TypeSystemService.ParseFile (project, currentParseFile, mimeType, currentParseText, token).ContinueWith (task => { + if (token.IsCancellationRequested) + return; + Application.Invoke (delegate { + // this may be called after the document has closed, in that case the OnDocumentParsed event shouldn't be invoked. + if (isClosed || task.Result == null || token.IsCancellationRequested) + return; + this.parsedDocument = task.Result; + OnDocumentParsed (EventArgs.Empty); + }); + }, TaskContinuationOptions.OnlyOnRanToCompletion); + } parseTimeout = 0; - return false; }); - } + }); } /// <summary> /// This method kicks off an async document parser and should be used instead of /// <see cref="UpdateParseDocument"/> unless you need the parsed document immediately. /// </summary> - public void ReparseDocument () + public override void ReparseDocument () { StartReparseThread (); } @@ -855,8 +879,8 @@ namespace MonoDevelop.Ide.Gui internal object ExtendedCommandTargetChain { get { // Only go through the text editor chain, if the text editor is selected as subview - if (Window != null && Window.ActiveViewContent.GetContent (typeof(IExtensibleTextEditor)) != null) - return editorExtension; + if (Window != null && Window.ActiveViewContent.GetContent (typeof(TextEditor)) != null) + return Editor.CommandRouter; return null; } } @@ -867,19 +891,10 @@ namespace MonoDevelop.Ide.Gui window.ViewContent.Project = null; } - protected virtual void OnDocumentParsed (EventArgs e) - { - EventHandler handler = this.DocumentParsed; - if (handler != null) - handler (this, e); - } - public event EventHandler Closed; - public event EventHandler Saved; public event EventHandler ViewChanged; - public event EventHandler DocumentParsed; - + public string[] CommentTags { get { if (IsFile) @@ -893,30 +908,16 @@ namespace MonoDevelop.Ide.Gui { //Document doc = IdeApp.Workbench.ActiveDocument; string loadedMimeType = DesktopService.GetMimeTypeForUri (fileName); - - Mono.TextEditor.Highlighting.SyntaxMode mode = null; - foreach (string mt in DesktopService.GetMimeTypeInheritanceChain (loadedMimeType)) { - mode = Mono.TextEditor.Highlighting.SyntaxModeService.GetSyntaxMode (null, mt); - if (mode != null) - break; - } - - if (mode == null) - return null; - - List<string> ctags; - if (mode.Properties.TryGetValue ("LineComment", out ctags) && ctags.Count > 0) { - return new string [] { ctags [0] }; - } - List<string> tags = new List<string> (); - if (mode.Properties.TryGetValue ("BlockCommentStart", out ctags)) - tags.Add (ctags [0]); - if (mode.Properties.TryGetValue ("BlockCommentEnd", out ctags)) - tags.Add (ctags [0]); - if (tags.Count == 2) - return tags.ToArray (); - else - return null; + + var result = TextEditorFactory.GetSyntaxProperties (loadedMimeType, "LineComment"); + if (result != null) + return result; + + var start = TextEditorFactory.GetSyntaxProperties (loadedMimeType, "BlockCommentStart"); + var end = TextEditorFactory.GetSyntaxProperties (loadedMimeType, "BlockCommentEnd"); + if (start != null && end != null) + return new [] { start[0], end[0] }; + return null; } // public MonoDevelop.Projects.CodeGeneration.CodeGenerator CreateCodeGenerator () @@ -932,7 +933,29 @@ namespace MonoDevelop.Ide.Gui public void DisableAutoScroll () { if (IsFile) - Mono.TextEditor.Utils.FileSettingsStore.Remove (FileName); + FileSettingsStore.Remove (FileName); + } + + public override OptionSet GetOptionSet () + { + return TypeSystemService.Workspace.Options; + } + + internal override Task<IReadOnlyList<Editor.Projection.Projection>> GetPartialProjectionsAsync (CancellationToken cancellationToken = default(CancellationToken)) + { + var parser = TypeSystemService.GetParser (Editor.MimeType); + if (parser == null) + return null; + var projectFile = Project.GetProjectFile (Editor.FileName); + if (projectFile == null) + return null; + if (!parser.CanGenerateProjection (Editor.MimeType, projectFile.BuildAction, Project.SupportedLanguages)) + return null; + try { + return parser.GetPartialProjectionsAsync (this, Editor, parsedDocument, cancellationToken); + } catch (NotSupportedException) { + return null; + } } } |