From 4c3d93223cdba0017280b88f1af24ab9e48ffe9a Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 15 Jul 2005 09:55:36 +0000 Subject: [PATCH] TextEditorControl now auto-detects the file encoding. When saving, the file is saved with the old encoding. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@179 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../VBNetBinding/Project/Src/VBNetAmbience.cs | 24 +- .../Project/Src/Gui/TextEditorControlBase.cs | 228 ++++++++++++++---- .../Project/Src/Lexer/AbstractLexer.cs | 7 +- .../Project/Src/Lexer/CSharp/Lexer.cs | 6 +- .../Project/Src/Lexer/VBNet/Lexer.cs | 28 ++- .../IDEOptions/TaskListOptions.cs | 23 +- .../Project/Src/Gui/Pads/DefinitionViewPad.cs | 2 +- .../Services/ParserService/ParserService.cs | 7 +- .../Gui/Editor/TextEditorDisplayBinding.cs | 11 +- src/Main/Base/Test/NRefactoryResolverTests.cs | 99 +++++++- .../Services/PropertyService/Properties.cs | 9 +- src/Main/StartUp/Project/SharpDevelopMain.cs | 4 +- 12 files changed, 348 insertions(+), 100 deletions(-) diff --git a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetAmbience.cs b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetAmbience.cs index 2f3a5702c5..80261ca83f 100644 --- a/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetAmbience.cs +++ b/src/AddIns/BackendBindings/VBNetBinding/Project/Src/VBNetAmbience.cs @@ -174,12 +174,14 @@ namespace VBNetBinding builder.Append(""); } - builder.Append("(Of"); - for (int i = 0; i < c.TypeParameters.Count; ++i) { - if (i > 0) builder.Append(", "); - builder.Append(c.TypeParameters[i].Name); + if (c.TypeParameters.Count > 0) { + builder.Append("(Of"); + for (int i = 0; i < c.TypeParameters.Count; ++i) { + if (i > 0) builder.Append(", "); + builder.Append(c.TypeParameters[i].Name); + } + builder.Append(')'); } - builder.Append(')'); if (c.ClassType == ClassType.Delegate) { builder.Append("("); @@ -461,12 +463,14 @@ namespace VBNetBinding builder.Append(""); } - builder.Append("(Of"); - for (int i = 0; i < m.TypeParameters.Count; ++i) { - if (i > 0) builder.Append(", "); - builder.Append(m.TypeParameters[i].Name); + if (m.TypeParameters.Count > 0) { + builder.Append("(Of"); + for (int i = 0; i < m.TypeParameters.Count; ++i) { + if (i > 0) builder.Append(", "); + builder.Append(m.TypeParameters[i].Name); + } + builder.Append(')'); } - builder.Append(')'); builder.Append("("); if (IncludeHTMLMarkup) builder.Append("
"); diff --git a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs index 8c8d31ce56..85d2e1e08b 100644 --- a/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs +++ b/src/Libraries/ICSharpCode.TextEditor/Project/Src/Gui/TextEditorControlBase.cs @@ -23,7 +23,7 @@ using System.Text; using ICSharpCode.TextEditor.Gui.CompletionWindow; using ICSharpCode.TextEditor.Document; using ICSharpCode.TextEditor.Actions; - + namespace ICSharpCode.TextEditor { /// @@ -53,19 +53,19 @@ namespace ICSharpCode.TextEditor } } + Encoding encoding; + /// /// Current file's character encoding /// public Encoding Encoding { get { - return TextEditorProperties.Encoding; + if (encoding == null) + return TextEditorProperties.Encoding; + return encoding; } set { -// if (encoding != null && value != null && !encoding.Equals(value) && !CharacterEncoding.IsUnicode(value)) { -// Byte[] bytes = encoding.GetBytes(Text); -// Text = new String(value.GetChars(bytes)); -// } - TextEditorProperties.Encoding = value; + encoding = value; } } @@ -144,7 +144,7 @@ namespace ICSharpCode.TextEditor [Browsable(false)] public bool IsInUpdate { get { - return this.updateLevel > 0; + return this.updateLevel > 0; } } @@ -158,7 +158,7 @@ namespace ICSharpCode.TextEditor } } -#region Document Properties + #region Document Properties /// /// If true spaces are shown in the textarea /// @@ -182,10 +182,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(false)] [Description("If true antialiased fonts are used inside the textarea")] public bool UseAntiAliasFont { - get { + get { return document.TextEditorProperties.UseAntiAliasedFont; } - set { + set { document.TextEditorProperties.UseAntiAliasedFont = value; OptionsChanged(); } @@ -198,7 +198,7 @@ namespace ICSharpCode.TextEditor [DefaultValue(false)] [Description("If true tabs are shown in the textarea")] public bool ShowTabs { - get { + get { return document.TextEditorProperties.ShowTabs; } set { @@ -230,10 +230,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(false)] [Description("If true the horizontal ruler is shown in the textarea")] public bool ShowHRuler { - get { + get { return document.TextEditorProperties.ShowHorizontalRuler; } - set { + set { document.TextEditorProperties.ShowHorizontalRuler = value; OptionsChanged(); } @@ -294,10 +294,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(true)] [Description("If true invalid lines are marked in the textarea")] public bool ShowInvalidLines { - get { + get { return document.TextEditorProperties.ShowInvalidLines; } - set { + set { document.TextEditorProperties.ShowInvalidLines = value; OptionsChanged(); } @@ -310,7 +310,7 @@ namespace ICSharpCode.TextEditor [DefaultValue(true)] [Description("If true folding is enabled in the textarea")] public bool EnableFolding { - get { + get { return document.TextEditorProperties.EnableFolding; } set { @@ -323,7 +323,7 @@ namespace ICSharpCode.TextEditor [DefaultValue(true)] [Description("If true matching brackets are highlighted")] public bool ShowMatchingBracket { - get { + get { return document.TextEditorProperties.ShowMatchingBracket; } set { @@ -336,7 +336,7 @@ namespace ICSharpCode.TextEditor [DefaultValue(true)] [Description("If true the icon bar is displayed")] public bool IsIconBarVisible { - get { + get { return document.TextEditorProperties.IsIconBarVisible; } set { @@ -352,10 +352,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(4)] [Description("The width in spaces of a tab character")] public int TabIndent { - get { + get { return document.TextEditorProperties.TabIndent; } - set { + set { document.TextEditorProperties.TabIndent = value; OptionsChanged(); } @@ -368,10 +368,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(LineViewerStyle.None)] [Description("The line viewer style")] public LineViewerStyle LineViewerStyle { - get { + get { return document.TextEditorProperties.LineViewerStyle; } - set { + set { document.TextEditorProperties.LineViewerStyle = value; OptionsChanged(); } @@ -384,10 +384,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(IndentStyle.Smart)] [Description("The indent style")] public IndentStyle IndentStyle { - get { + get { return document.TextEditorProperties.IndentStyle; } - set { + set { document.TextEditorProperties.IndentStyle = value; OptionsChanged(); } @@ -400,10 +400,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(false)] [Description("Converts tabs to spaces while typing")] public bool ConvertTabsToSpaces { - get { + get { return document.TextEditorProperties.ConvertTabsToSpaces; } - set { + set { document.TextEditorProperties.ConvertTabsToSpaces = value; OptionsChanged(); } @@ -416,10 +416,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(false)] [Description("Creates a backup copy for overwritten files")] public bool CreateBackupCopy { - get { + get { return document.TextEditorProperties.CreateBackupCopy; } - set { + set { document.TextEditorProperties.CreateBackupCopy = value; OptionsChanged(); } @@ -432,10 +432,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(false)] [Description("Hide the mouse cursor while typing")] public bool HideMouseCursor { - get { + get { return document.TextEditorProperties.HideMouseCursor; } - set { + set { document.TextEditorProperties.HideMouseCursor = value; OptionsChanged(); } @@ -448,10 +448,10 @@ namespace ICSharpCode.TextEditor [DefaultValue(false)] [Description("Allows the caret to be places beyonde the end of line")] public bool AllowCaretBeyondEOL { - get { + get { return document.TextEditorProperties.AllowCaretBeyondEOL; } - set { + set { document.TextEditorProperties.AllowCaretBeyondEOL = value; OptionsChanged(); } @@ -488,8 +488,8 @@ namespace ICSharpCode.TextEditor OptionsChanged(); } } - -#endregion + + #endregion public abstract TextAreaControl ActiveTextAreaControl { get; } @@ -510,7 +510,7 @@ namespace ICSharpCode.TextEditor } - + internal IEditAction GetEditAction(Keys keyData) { if (!editactions.ContainsKey(keyData)) { @@ -604,12 +604,16 @@ namespace ICSharpCode.TextEditor public void LoadFile(string fileName) { - LoadFile(fileName, true); + LoadFile(fileName, true, true); } + /// /// Loads a file given by fileName /// - public void LoadFile(string fileName, bool autoLoadHighlighting) + /// The name of the file to open + /// Automatically load the highlighting for the file + /// Automatically detect file encoding and set Encoding property to the detected encoding. + public void LoadFile(string fileName, bool autoLoadHighlighting, bool autodetectEncoding) { BeginUpdate(); document.TextContent = String.Empty; @@ -619,14 +623,40 @@ namespace ICSharpCode.TextEditor document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategyForFile(fileName); } - StreamReader stream; - if (Encoding != null) { - stream = new StreamReader(fileName, Encoding); - } else { - stream = new StreamReader(fileName); + using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { + StreamReader stream; + if (autodetectEncoding && fs.Length > 3) { + // the autodetection of StreamReader is not capable of detecting the difference + // between ISO-8859-1 and UTF-8 without BOM. + int firstByte = fs.ReadByte(); + int secondByte = fs.ReadByte(); + switch ((firstByte << 8) | secondByte) { + case 0x0000: // either UTF-32 Big Endian or a binary file; use StreamReader + case 0xfffe: // Unicode BOM (UTF-16 LE or UTF-32 LE) + case 0xfeff: // UTF-16 BE BOM + case 0xefbb: // start of UTF-8 BOM + // StreamReader autodetection works + fs.Position = 0; + stream = new StreamReader(fs); + break; + default: + stream = AutoDetect(fs, (byte)firstByte, (byte)secondByte); + break; + } + } else { + Encoding encoding = this.Encoding; + if (encoding != null) { + stream = new StreamReader(fs, encoding); + } else { + stream = new StreamReader(fs); + } + } + Document.TextContent = stream.ReadToEnd(); + if (autodetectEncoding) { + Encoding = stream.CurrentEncoding; + } + stream.Close(); } - Document.TextContent = stream.ReadToEnd(); - stream.Close(); this.FileName = fileName; OptionsChanged(); @@ -636,6 +666,103 @@ namespace ICSharpCode.TextEditor Refresh(); } + StreamReader AutoDetect(FileStream fs, byte firstByte, byte secondByte) + { + int max = (int)Math.Min(fs.Length, 500000); // look at max. 500 KB + const int ASCII = 0; + const int Error = 1; + const int UTF8 = 2; + const int UTF8Sequence = 3; + int state = ASCII; + int sequenceLength = 0; + byte b; + for (int i = 0; i < max; i++) { + if (i == 0) { + b = firstByte; + } else if (i == 1) { + b = secondByte; + } else { + b = (byte)fs.ReadByte(); + } + if (b < 0x80) { + // normal ASCII character + if (state == UTF8Sequence) { + state = Error; + break; + } + } else if (b < 0xc0) { + // 10xxxxxx : continues UTF8 byte sequence + if (state == UTF8Sequence) { + --sequenceLength; + if (sequenceLength < 0) { + state = Error; + break; + } else if (sequenceLength == 0) { + state = UTF8; + } + } else { + state = Error; + break; + } + } else if (b > 0xc2 && b < 0xf5) { + // beginning of byte sequence + if (state == UTF8 || state == ASCII) { + state = UTF8Sequence; + if (b < 0xe0) { + sequenceLength = 1; // one more byte following + } else if (b < 0xf0) { + sequenceLength = 2; // two more bytes following + } else { + sequenceLength = 3; // three more bytes following + } + } else { + state = Error; + break; + } + } else { + // 0xc0, 0xc1, 0xf5 to 0xff are invalid in UTF-8 (see RFC 3629) + state = Error; + break; + } + } + fs.Position = 0; + switch (state) { + case ASCII: + // when the file seems to be ASCII, we read it using the user-specified encoding + // so it is saved again using that encoding. + return new StreamReader(fs, this.TextEditorProperties.Encoding); + case Error: + Encoding defaultEncoding = this.TextEditorProperties.Encoding; + if (IsUnicode(defaultEncoding)) { + // the file is not Unicode, so don't read it using Unicode even if the + // user has choosen Unicode as the default encoding. + defaultEncoding = Encoding.Default; // use system encoding instead + } + return new StreamReader(fs, defaultEncoding); + default: + return new StreamReader(fs); + } + } + + /// + /// Gets if the document can be saved with the current encoding without losing data. + /// + public bool CanSaveWithCurrentEncoding() + { + if (encoding == null || IsUnicode(encoding)) + return true; + // not a unicode codepage + string text = document.TextContent; + return encoding.GetString(encoding.GetBytes(text)) == text; + } + + bool IsUnicode(Encoding encoding) + { + int codepage = encoding.CodePage; + // return true if codepage is any UTF codepage + return codepage == 65001 || codepage == 65000 || codepage == 1200 || codepage == 1201; + } + /// /// Saves a file given by fileName /// @@ -646,10 +773,11 @@ namespace ICSharpCode.TextEditor } StreamWriter stream; - if (Encoding != null && Encoding.CodePage != 65001) { - stream = new StreamWriter(fileName, false, Encoding); + Encoding encoding = this.Encoding; + if (encoding == null) { // use UTF8 with BOM by default + stream = new StreamWriter(fileName, false, Encoding.UTF8); } else { - stream = new StreamWriter(fileName, false); + stream = new StreamWriter(fileName, false, encoding); } foreach (LineSegment line in Document.LineSegmentCollection) { @@ -662,7 +790,7 @@ namespace ICSharpCode.TextEditor this.FileName = fileName; } - void MakeBackupCopy(string fileName) + void MakeBackupCopy(string fileName) { try { if (File.Exists(fileName)) { @@ -670,7 +798,7 @@ namespace ICSharpCode.TextEditor File.Copy(fileName, backupName, true); } } catch (Exception) { -// +// // MessageService.ShowError(e, "Can not create backup copy of " + fileName); } } diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs index a3eea8f723..8cd2e4bd53 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/AbstractLexer.cs @@ -70,10 +70,11 @@ namespace ICSharpCode.NRefactory.Parser } set { specialCommentTags = value; - specialCommentHash = new Hashtable(); - if (specialCommentTags != null) { + specialCommentHash = null; + if (specialCommentTags != null && specialCommentTags.Length > 0) { + specialCommentHash = new Hashtable(); foreach (string str in specialCommentTags) { - specialCommentHash[str] = 0; + specialCommentHash.Add(str, null); } } } diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs index 78e53d48e8..d8fd42e67f 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/CSharp/Lexer.cs @@ -754,7 +754,7 @@ namespace ICSharpCode.NRefactory.Parser.CSharp } else { string tag = curWord.ToString(); curWord.Length = 0; - if (specialCommentHash[tag] != null) { + if (specialCommentHash.ContainsKey(tag)) { Point p = new Point(col ,line); string comment = ReadToEOL(); tagComments.Add(new TagComment(tag, comment, p)); @@ -771,14 +771,14 @@ namespace ICSharpCode.NRefactory.Parser.CSharp void ReadSingleLineComment(CommentType commentType) { - specialTracker.StartComment(commentType, new Point(line, col)); + specialTracker.StartComment(commentType, new Point(col, line)); specialTracker.AddString(ReadCommentToEOL()); specialTracker.FinishComment(); } void ReadMultiLineComment() { - specialTracker.StartComment(CommentType.Block, new Point(line, col)); + specialTracker.StartComment(CommentType.Block, new Point(col, line)); int nextChar; while ((nextChar = reader.Read()) != -1) { char ch = (char)nextChar; diff --git a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs index 8ed4cc7415..7e8a6c6470 100644 --- a/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs +++ b/src/Libraries/NRefactory/Project/Src/Lexer/VBNet/Lexer.cs @@ -503,9 +503,9 @@ namespace ICSharpCode.NRefactory.Parser.VB void ReadComment() { - specialTracker.StartComment(CommentType.SingleLine, new Point(line, col)); + specialTracker.StartComment(CommentType.SingleLine, new Point(col, line)); sb.Length = 0; - StringBuilder curWord = new StringBuilder(); + StringBuilder curWord = specialCommentHash != null ? new StringBuilder() : null; int x = col; int y = line; int nextChar; @@ -517,16 +517,20 @@ namespace ICSharpCode.NRefactory.Parser.VB break; } - if (Char.IsLetter(ch)) { - curWord.Append(ch); - } else { - string tag = curWord.ToString(); - curWord.Length = 0; - if (specialCommentHash != null && specialCommentHash[tag] != null) { - Point p = new Point(col, line); - sb.Append(ReadToEOL()); - tagComments.Add(new TagComment(tag, sb.ToString(), p)); - break; + if (specialCommentHash != null) { + if (Char.IsLetter(ch)) { + curWord.Append(ch); + } else { + string tag = curWord.ToString(); + curWord.Length = 0; + if (specialCommentHash.ContainsKey(tag)) { + Point p = new Point(col ,line); + string comment = ReadToEOL(); + tagComments.Add(new TagComment(tag, comment, p)); + sb.Append(tag); + sb.Append(comment); + break; + } } } } diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/TaskListOptions.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/TaskListOptions.cs index 9c03656660..d00fa74c8e 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/TaskListOptions.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/TaskListOptions.cs @@ -23,19 +23,20 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels const string changeButton = "changeButton"; const string removeButton = "removeButton"; const string addButton = "addButton"; + ListView taskList; public override void LoadPanelContents() { SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("Resources.TaskListOptions.xfrm")); - string tasklisttokens = PropertyService.Get("SharpDevelop.TaskListTokens", "HACK;TODO;UNDONE;FIXME"); - string[] tokens = tasklisttokens.Split(';'); - ((ListView)ControlDictionary[taskListView]).BeginUpdate(); + string[] tokens = PropertyService.Get("SharpDevelop.TaskListTokens", ParserService.DefaultTaskListTokens); + taskList = (ListView)ControlDictionary[taskListView]; + taskList.BeginUpdate(); foreach (string token in tokens) { - ((ListView)ControlDictionary[taskListView]).Items.Add(new ListViewItem(token)); + taskList.Items.Add(token); } - ((ListView)ControlDictionary[taskListView]).EndUpdate(); - ((ListView)ControlDictionary[taskListView]).SelectedIndexChanged += new EventHandler(TaskListViewSelectedIndexChanged); + taskList.EndUpdate(); + taskList.SelectedIndexChanged += new EventHandler(TaskListViewSelectedIndexChanged); ControlDictionary[changeButton].Click += new EventHandler(ChangeButtonClick); ControlDictionary[removeButton].Click += new EventHandler(RemoveButtonClick); @@ -47,11 +48,15 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels public override bool StorePanelContents() { ArrayList tokens = new ArrayList(); - foreach (ListViewItem item in ((ListView)ControlDictionary[taskListView]).Items) { - tokens.Add(item.Text); + + foreach (ListViewItem item in taskList.Items) { + string text = item.Text.Trim(); + if (text.Length > 0) { + tokens.Add(text); + } } - PropertyService.Set("SharpDevelop.TaskListTokens", String.Join(";", (string[])tokens.ToArray(typeof(string)))); + PropertyService.Set("SharpDevelop.TaskListTokens", tokens.ToArray(typeof(string))); return true; } diff --git a/src/Main/Base/Project/Src/Gui/Pads/DefinitionViewPad.cs b/src/Main/Base/Project/Src/Gui/Pads/DefinitionViewPad.cs index f667b15281..a96f20a774 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/DefinitionViewPad.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/DefinitionViewPad.cs @@ -93,7 +93,7 @@ namespace ICSharpCode.SharpDevelop.Gui if (pos.Equals(oldPosition)) return; oldPosition = pos; if (pos.Filename != ctl.FileName) - ctl.LoadFile(pos.Filename); + ctl.LoadFile(pos.Filename, true, true); // TODO: get AutoDetectEncoding from settings ctl.ActiveTextAreaControl.ScrollTo(int.MaxValue); // scroll completely down ctl.ActiveTextAreaControl.Caret.Line = pos.Line - 1; ctl.ActiveTextAreaControl.ScrollToCaret(); // scroll up to search position diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs index 31def50aae..be7b290c9b 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParserService.cs @@ -128,7 +128,7 @@ namespace ICSharpCode.Core ParseProjectContent newContent = ParseProjectContent.CreateUninitalized(project); lock (projectContents) { projectContents[project] = newContent; - } + } createdContents.Add(newContent); } catch (Exception e) { Console.WriteLine("Error while retrieving project contents from {0}:", project); @@ -392,6 +392,8 @@ namespace ICSharpCode.Core return null; } + public static readonly string[] DefaultTaskListTokens = {"HACK", "TODO", "UNDONE", "FIXME"}; + public static IParser GetParser(string fileName) { IParser curParser = null; @@ -403,8 +405,7 @@ namespace ICSharpCode.Core } if (curParser != null) { - string tasklisttokens = PropertyService.Get("SharpDevelop.TaskListTokens", "HACK;TODO;UNDONE;FIXME"); - curParser.LexerTags = tasklisttokens.Split(';'); + curParser.LexerTags = PropertyService.Get("SharpDevelop.TaskListTokens", DefaultTaskListTokens); } return curParser; diff --git a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs index eaa968497f..ef4d4ee481 100644 --- a/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs +++ b/src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs @@ -304,6 +304,14 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor } // KSL End + if (!textAreaControl.CanSaveWithCurrentEncoding()) { + if (MessageService.AskQuestion("The file cannot be saved with the current encoding " + + textAreaControl.Encoding.EncodingName + " without losing data." + + "\nDo you want to save it using UTF-8 instead?")) { + textAreaControl.Encoding = System.Text.Encoding.UTF8; + } + } + textAreaControl.SaveFile(fileName); FileName = fileName; TitleName = Path.GetFileName(fileName); @@ -317,7 +325,8 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor { textAreaControl.IsReadOnly = (File.GetAttributes(fileName) & FileAttributes.ReadOnly) == FileAttributes.ReadOnly; - textAreaControl.LoadFile(fileName); + bool autodetectEncoding = true; + textAreaControl.LoadFile(fileName, true, autodetectEncoding); FileName = fileName; TitleName = Path.GetFileName(fileName); IsDirty = false; diff --git a/src/Main/Base/Test/NRefactoryResolverTests.cs b/src/Main/Base/Test/NRefactoryResolverTests.cs index 41635b2d97..b973e9c528 100644 --- a/src/Main/Base/Test/NRefactoryResolverTests.cs +++ b/src/Main/Base/Test/NRefactoryResolverTests.cs @@ -364,6 +364,21 @@ interface IInterface2 { Assert.AreEqual("dblVal", m.Parameters[0].Name, "new A(11.1) parameter"); } + [Test] + public void DefaultCTorOverloadLookupTest() + { + string program = @"class A { + void Method() { + + } +} +"; + ResolveResult result = Resolve(program, "new A()", 3); + Assert.IsNotNull(result); + IMethod m = (IMethod)((MemberResolveResult)result).ResolvedMember; + Assert.IsNotNull(m); + } + [Test] public void AnonymousMethodParameters() { @@ -466,6 +481,22 @@ class B { Assert.AreEqual("System.Activator", result.ResolvedType.FullyQualifiedName); } + [Test] + public void InnerClassTest() + { + string program = @"using System; +class A { + +} +"; + ResolveResult result = Resolve(program, "Environment.SpecialFolder", 3); + Assert.IsNotNull(result); + Assert.IsTrue(result is TypeResolveResult); + Assert.AreEqual("System.Environment.SpecialFolder", result.ResolvedType.FullyQualifiedName); + } + #endregion + + #region Import namespace tests [Test] public void NamespacePreferenceTest() { @@ -489,17 +520,75 @@ class Activator { } [Test] - public void InnerClassTest() + public void ImportedSubnamespaceTestCSharp() { + // using an import in this way is not possible in C# string program = @"using System; class A { + void Test() { + Collections.ArrayList a; + + } +} +"; + ResolveResult result = Resolve(program, "Collections.ArrayList", 4); + Assert.IsNull(result, "Collections.ArrayList should not resolve"); + LocalResolveResult local = Resolve(program, "a", 5) as LocalResolveResult; + Assert.IsNotNull(local, "a should resolve to a local variable"); + Assert.AreEqual("Collections.ArrayList", local.ResolvedType.FullyQualifiedName, + "the full type should not be resolved"); + } + + [Test] + public void ImportedSubnamespaceTestVBNet() + { + // using an import this way IS possible in VB.NET + string program = @"Imports System +Class A + Sub Test() + Dim a As Collections.ArrayList + End Sub +End Class +"; + TypeResolveResult type = ResolveVB(program, "Collections.ArrayList", 4) as TypeResolveResult; + Assert.IsNotNull(type, "Collections.ArrayList should resolve to a type"); + Assert.AreEqual("System.Collections.ArrayList", type.ResolvedClass.FullyQualifiedName, "TypeResolveResult"); + LocalResolveResult local = ResolveVB(program, "a", 5) as LocalResolveResult; + Assert.IsNotNull(local, "a should resolve to a local variable"); + Assert.AreEqual("System.Collections.ArrayList", local.ResolvedType.FullyQualifiedName, + "the full type should be resolved"); + } + + [Test] + public void ImportAliasTest() + { + string program = @"using System.Collections = COL; +class A { + void Test() { + COL.ArrayList a; + + } } "; - ResolveResult result = Resolve(program, "Environment.SpecialFolder", 3); - Assert.IsNotNull(result); - Assert.IsTrue(result is TypeResolveResult); - Assert.AreEqual("System.Environment.SpecialFolder", result.ResolvedType.FullyQualifiedName); + TypeResolveResult type = Resolve(program, "COL.ArrayList", 4) as TypeResolveResult; + Assert.IsNotNull(type, "COL.ArrayList should resolve to a type"); + Assert.AreEqual("System.Collections.ArrayList", type.ResolvedClass.FullyQualifiedName, "TypeResolveResult"); + LocalResolveResult local = Resolve(program, "a", 5) as LocalResolveResult; + Assert.IsNotNull(local, "a should resolve to a local variable"); + Assert.AreEqual("System.Collections.ArrayList", local.ResolvedType.FullyQualifiedName, + "the full type should be resolved"); + } + + [Test] + public void ImportAliasNamespaceResolveTest() + { + NamespaceResolveResult ns; + string program = "using System.Collections = COL;\r\nclass A {\r\n}\r\n"; + ns = Resolve(program, "COL", 3) as NamespaceResolveResult; + Assert.AreEqual("System.Collections", ns.Name, "COL"); + ns = Resolve(program, "COL.Generic", 3) as NamespaceResolveResult; + Assert.AreEqual("System.Collections.Generic", ns.Name, "COL.Generic"); } #endregion } diff --git a/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs b/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs index b369c74775..5a9feffbaa 100644 --- a/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs +++ b/src/Main/Core/Project/Src/Services/PropertyService/Properties.cs @@ -136,6 +136,8 @@ namespace ICSharpCode.Core ArrayList ReadArray(XmlTextReader reader) { + if (reader.IsEmptyElement) + return new ArrayList(0); ArrayList l = new ArrayList(); while (reader.Read()) { switch (reader.NodeType) { @@ -239,7 +241,12 @@ namespace ICSharpCode.Core if (o is string && typeof(T) != typeof(string)) { TypeConverter c = TypeDescriptor.GetConverter(typeof(T)); - o = c.ConvertFromInvariantString(o.ToString()); + try { + o = c.ConvertFromInvariantString(o.ToString()); + } catch (NotSupportedException ex) { + MessageService.ShowWarning("Error loading property '" + property + "': " + ex.Message); + o = defaultValue; + } properties[property] = o; // store for future look up } else if (o is ArrayList && typeof(T).IsArray) { ArrayList list = (ArrayList)o; diff --git a/src/Main/StartUp/Project/SharpDevelopMain.cs b/src/Main/StartUp/Project/SharpDevelopMain.cs index c2041b192d..ea37bd38eb 100644 --- a/src/Main/StartUp/Project/SharpDevelopMain.cs +++ b/src/Main/StartUp/Project/SharpDevelopMain.cs @@ -1,7 +1,7 @@ -// +// // // -// +// // //