Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/monodevelop.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorLluis Sanchez <llsan@microsoft.com>2019-06-04 15:01:31 +0300
committerLluis Sanchez <llsan@microsoft.com>2019-06-04 15:01:31 +0300
commit046482870c9040954dd3b9296d719e26c1216eec (patch)
tree0f81ceaf655fd2021ee3adf24a7b7a89e776f619 /main
parent2adc4c688539386a99182246487a90983bd81d84 (diff)
Fix mime type assignment issues in FileModel
The MimeType property was not properly set in some cases, such as when creating a new file, or when saving a file with a new name and extension. FileModel now ensures that the MimeType property is always up to date, and TextBufferFileModel now updates the content type of the buffer when creating a new document or when saving a document. Fixes VSTS# 825629 - No error message shows up in TypeScript files
Diffstat (limited to 'main')
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/DocumentModel.cs8
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileDocumentController.cs2
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileModel.cs36
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/ModelRepresentation.cs22
-rw-r--r--main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/TextBufferFileModel.cs18
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/FileModelTests.cs49
-rw-r--r--main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/TextBufferFileModelTests.cs31
7 files changed, 149 insertions, 17 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/DocumentModel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/DocumentModel.cs
index 18e0b74522..e05ed9f1c2 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/DocumentModel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/DocumentModel.cs
@@ -103,14 +103,20 @@ namespace MonoDevelop.Ide.Gui.Documents
public void CreateNew ()
{
+ InitializeNew ();
+ ModelRepresentation.CreateNew ();
+ }
+
+ protected void InitializeNew ()
+ {
if (IsLoaded)
throw new InvalidOperationException ("Model already loaded");
if (Data.IsLinked)
throw new InvalidOperationException ("Model already linked");
isNew = true;
- ModelRepresentation.CreateNew ();
}
+
public bool IsNew {
get {
CheckInitialized ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileDocumentController.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileDocumentController.cs
index fc2801d171..2ecfd021c1 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileDocumentController.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileDocumentController.cs
@@ -110,7 +110,7 @@ namespace MonoDevelop.Ide.Gui.Documents
if (!typeof (FileModel).IsAssignableFrom (FileModelType))
throw new InvalidOperationException ("Invalid file model type: " + FileModelType);
var fileModel = (FileModel)Activator.CreateInstance (FileModelType);
- fileModel.CreateNew ();
+ fileModel.CreateNew (fileDescriptor.FilePath, fileDescriptor.MimeType);
await fileModel.SetContent (fileDescriptor.Content);
if (fileDescriptor.Encoding != null && fileModel is TextFileModel textFileModel)
textFileModel.Encoding = fileDescriptor.Encoding;
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileModel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileModel.cs
index 2d0b324dc6..b2c3ed6f24 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileModel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/FileModel.cs
@@ -41,9 +41,9 @@ namespace MonoDevelop.Ide.Gui.Documents
{
}
- public string MimeType { get; set; }
+ public string MimeType => IsLoaded ? GetRepresentation<FileModelRepresentation> ().MimeType : null;
- public FilePath FilePath => Id != null ? (FilePath)Id : FilePath.Null;
+ public FilePath FilePath => Id != null ? (FilePath) Id : (IsLoaded ? GetRepresentation<FileModelRepresentation> ().FilePath : FilePath.Null);
public bool CanWrite {
get {
@@ -57,6 +57,14 @@ namespace MonoDevelop.Ide.Gui.Documents
}
}
+ public void CreateNew (string fileName, string mimeType)
+ {
+ InitializeNew ();
+ var rep = GetRepresentation<FileModelRepresentation> ();
+ rep.InitUnsaved (fileName, mimeType);
+ rep.CreateNew ();
+ }
+
public Task LinkToFile (FilePath filePath)
{
if (FilePath != filePath)
@@ -70,10 +78,10 @@ namespace MonoDevelop.Ide.Gui.Documents
await UnlinkFromId ();
}
- public Task SaveAs (FilePath filePath)
+ public async Task SaveAs (FilePath filePath)
{
- LinkToFile (filePath);
- return Save ();
+ await LinkToFile (filePath);
+ await Save ();
}
/// <summary>
@@ -99,9 +107,20 @@ namespace MonoDevelop.Ide.Gui.Documents
protected abstract class FileModelRepresentation : ModelRepresentation
{
- public FilePath FilePath => Id != null ? (FilePath)Id : FilePath.Null;
+ FilePath unsavedFilePath;
+
+ public FilePath FilePath => Id != null ? (FilePath)Id : unsavedFilePath;
public string MimeType { get; set; }
+ internal void InitUnsaved (FilePath filePath, string mimeType)
+ {
+ unsavedFilePath = filePath;
+ if (mimeType != null)
+ MimeType = mimeType;
+ else if (!filePath.IsNullOrEmpty)
+ MimeType = Runtime.PeekService<DesktopService> ()?.GetMimeTypeForUri (filePath);
+ }
+
public async Task SetContent (Stream content)
{
try {
@@ -128,6 +147,11 @@ namespace MonoDevelop.Ide.Gui.Documents
} else
throw new InvalidOperationException ($"Can't copy data from model of type {other.GetType ()} into a model of type {GetType ()}");
}
+
+ protected override async Task OnIdChanged ()
+ {
+ MimeType = (await Runtime.GetService<DesktopService> ()).GetMimeTypeForUri (FilePath);
+ }
}
class InternalFileModelRepresentation : FileModelRepresentation
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/ModelRepresentation.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/ModelRepresentation.cs
index bdbde45d4c..8ca0506274 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/ModelRepresentation.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/ModelRepresentation.cs
@@ -68,6 +68,7 @@ namespace MonoDevelop.Ide.Gui.Documents
{
try {
await WaitHandle.WaitAsync ();
+ await CheckIdChange ();
if (IsLoaded)
return;
if (DocumentModelData.IsLinked)
@@ -96,6 +97,7 @@ namespace MonoDevelop.Ide.Gui.Documents
{
try {
await WaitHandle.WaitAsync ();
+ await CheckIdChange ();
await OnLoad ();
IsLoaded = true;
HasUnsavedChanges = false;
@@ -108,6 +110,7 @@ namespace MonoDevelop.Ide.Gui.Documents
{
try {
await WaitHandle.WaitAsync ();
+ await CheckIdChange ();
await OnSave ();
HasUnsavedChanges = false;
} finally {
@@ -138,6 +141,25 @@ namespace MonoDevelop.Ide.Gui.Documents
protected abstract void OnCreateNew ();
+ /// <summary>
+ /// Invoked just before a load or save operation when the Id of a model has changed
+ /// </summary>
+ protected virtual Task OnIdChanged ()
+ {
+ return Task.CompletedTask;
+ }
+
+ object id;
+
+ Task CheckIdChange ()
+ {
+ if (id != Id) {
+ id = Id;
+ return OnIdChanged ();
+ } else
+ return Task.CompletedTask;
+ }
+
protected abstract Task OnLoad ();
protected abstract Task OnSave ();
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/TextBufferFileModel.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/TextBufferFileModel.cs
index 5b3e7db3c6..59f3193212 100644
--- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/TextBufferFileModel.cs
+++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.Gui.Documents/TextBufferFileModel.cs
@@ -66,8 +66,7 @@ namespace MonoDevelop.Ide.Gui.Documents
protected override async Task OnLoad ()
{
var text = await TextFileUtility.GetTextAsync (FilePath, CancellationToken.None);
- MimeType = (await Runtime.GetService<DesktopService> ()).GetMimeTypeForUri (FilePath);
- var contentType = (MimeType == null) ? PlatformCatalog.Instance.TextBufferFactoryService.InertContentType : GetContentTypeFromMimeType (FilePath, MimeType);
+ var contentType = GetContentTypeFromMimeType ();
if (textDocument != null) {
// Reloading
try {
@@ -115,6 +114,10 @@ namespace MonoDevelop.Ide.Gui.Documents
protected override Task OnSave ()
{
+ var contentType = GetContentTypeFromMimeType ();
+ if (textDocument.TextBuffer.ContentType != contentType)
+ textDocument.TextBuffer.ChangeContentType (contentType, null);
+
// OnLoad is always called before anything else, so the document should be ready
textDocument.SaveAs (FilePath, true);
cleanReiteratedVersion = textDocument.TextBuffer.CurrentSnapshot.Version.ReiteratedVersionNumber;
@@ -126,17 +129,18 @@ namespace MonoDevelop.Ide.Gui.Documents
ITextDocument CreateTextDocument (string text)
{
- var contentType = (MimeType == null)
- ? PlatformCatalog.Instance.TextBufferFactoryService.InertContentType
- : GetContentTypeFromMimeType (FilePath, MimeType);
+ var contentType = GetContentTypeFromMimeType ();
var buffer = PlatformCatalog.Instance.TextBufferFactoryService.CreateTextBuffer (text, contentType);
var doc = PlatformCatalog.Instance.TextDocumentFactoryService.CreateTextDocument (buffer, FilePath.ToString () ?? "");
return doc;
}
- protected static IContentType GetContentTypeFromMimeType (string filePath, string mimeType)
+ IContentType GetContentTypeFromMimeType ()
{
- return MimeTypeCatalog.Instance.GetContentTypeForMimeType (mimeType, filePath)
+ if (MimeType == null)
+ return PlatformCatalog.Instance.TextBufferFactoryService.InertContentType;
+
+ return MimeTypeCatalog.Instance.GetContentTypeForMimeType (MimeType, FilePath)
?? PlatformCatalog.Instance.ContentTypeRegistryService.GetContentType ("text");
}
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/FileModelTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/FileModelTests.cs
index a6868183b9..a31145b40a 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/FileModelTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/FileModelTests.cs
@@ -29,10 +29,12 @@ using NUnit.Framework;
using System.IO;
using System.Threading.Tasks;
using MonoDevelop.Core;
+using UnitTests;
namespace MonoDevelop.Ide.Gui.DocumentModels
{
- public class FileModelTests: DocumentModelTestsBase
+ [RequireService(typeof(DesktopService))]
+ public class FileModelTests : DocumentModelTestsBase
{
string tempFile;
@@ -154,7 +156,7 @@ namespace MonoDevelop.Ide.Gui.DocumentModels
var file = CreateFileModel ();
await file.LinkToFile (fileName);
- Assert.AreEqual (fileName, file.FilePath.ToString());
+ Assert.AreEqual (fileName, file.FilePath.ToString ());
Assert.IsFalse (file.IsNew);
Assert.IsFalse (file.IsLoaded);
Assert.IsFalse (file.HasUnsavedChanges);
@@ -171,6 +173,20 @@ namespace MonoDevelop.Ide.Gui.DocumentModels
}
[Test]
+ public async Task UnsharedFileModelLoadSetsMimeType ()
+ {
+ var dir = Util.CreateTmpDir ("UnsharedFileModelLoadSetsMimeType");
+ var fileName = Path.Combine (dir, "Foo.cs");
+ File.WriteAllText (fileName, "Foo");
+
+ var file = CreateFileModel ();
+ await file.LinkToFile (fileName);
+ Assert.AreEqual (null, file.MimeType);
+ await file.Load ();
+ Assert.AreEqual ("text/x-csharp", file.MimeType);
+ }
+
+ [Test]
public async Task UnsharedFileModelChangeEvents ()
{
int changedCount = 0;
@@ -259,5 +275,34 @@ namespace MonoDevelop.Ide.Gui.DocumentModels
File.Delete (fileName);
}
}
+
+ [Test]
+ public void CreateNewFile ()
+ {
+ using (var model = CreateFileModel ()) {
+ model.CreateNew ("foo.cs", null);
+ Assert.AreEqual ("foo.cs", model.FilePath.ToString ());
+ Assert.AreEqual ("text/x-csharp", model.MimeType);
+ }
+ using (var model = CreateFileModel ()) {
+ model.CreateNew (null, "text/x-csharp");
+ Assert.AreEqual (FilePath.Null, model.FilePath);
+ Assert.AreEqual ("text/x-csharp", model.MimeType);
+ }
+ }
+
+ [Test]
+ public async Task CreateNewFileRenameWhenSaving ()
+ {
+ using (var model = CreateFileModel ()) {
+ model.CreateNew ("foo.cs", null);
+
+ var dir = UnitTests.Util.CreateTmpDir ("CreateNewFileRenameWhenSaving");
+ var file = Path.Combine (dir, "bar.txt");
+ await model.SaveAs (file);
+ Assert.AreEqual ("text/plain", model.MimeType);
+ Assert.AreEqual (file, model.FilePath.ToString ());
+ }
+ }
}
}
diff --git a/main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/TextBufferFileModelTests.cs b/main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/TextBufferFileModelTests.cs
index f5df67d105..f3805b8f47 100644
--- a/main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/TextBufferFileModelTests.cs
+++ b/main/tests/Ide.Tests/MonoDevelop.Ide.Gui.DocumentModels/TextBufferFileModelTests.cs
@@ -24,7 +24,11 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
+using System.IO;
+using System.Threading.Tasks;
+using MonoDevelop.Core;
using MonoDevelop.Ide.Gui.Documents;
+using NUnit.Framework;
namespace MonoDevelop.Ide.Gui.DocumentModels
{
@@ -34,5 +38,32 @@ namespace MonoDevelop.Ide.Gui.DocumentModels
{
return new TextBufferFileModel ();
}
+
+ [Test]
+ public void CreateNewTextBufferFile ()
+ {
+ using (var model = new TextBufferFileModel ()) {
+ model.CreateNew ("foo.cs", null);
+ Assert.AreEqual ("CSharp", model.TextBuffer.ContentType.TypeName);
+ }
+ using (var model = new TextBufferFileModel ()) {
+ model.CreateNew (null, "text/x-csharp");
+ Assert.AreEqual ("CSharp", model.TextBuffer.ContentType.TypeName);
+ }
+ }
+
+ [Test]
+ public async Task CreateNewTextBufferFileRenameWhenSaving ()
+ {
+ using (var model = new TextBufferFileModel ()) {
+ model.CreateNew ("foo.cs", null);
+ Assert.AreEqual ("CSharp", model.TextBuffer.ContentType.TypeName);
+
+ var dir = UnitTests.Util.CreateTmpDir ("CreateNewFileRenameWhenSaving");
+ var file = Path.Combine (dir, "bar.txt");
+ await model.SaveAs (file);
+ Assert.AreEqual ("text", model.TextBuffer.ContentType.TypeName);
+ }
+ }
}
}