Browse Source

Fixed SD2-293 (Creating any C++ Project fails with a NullReferenceException).

Fixed exception when quickly closing multiple files during the initial parser run.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@322 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
Daniel Grunwald 20 years ago
parent
commit
622070a221
  1. 12
      src/Main/Base/Project/Src/Internal/Templates/Project/CombineDescriptor.cs
  2. 2
      src/Main/Base/Project/Src/Internal/Templates/Project/ProjectDescriptor.cs
  3. 33
      src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentEnumerator.cs
  4. 8
      src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs

12
src/Main/Base/Project/Src/Internal/Templates/Project/CombineDescriptor.cs

@ -26,7 +26,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
string name; string name;
string startupProject = null; string startupProject = null;
string relativeDirectory = null; string relativeDirectory = null;
#region public properties #region public properties
public string StartupProject { public string StartupProject {
get { get {
@ -77,10 +77,10 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
// Create sub projects // Create sub projects
foreach (ProjectDescriptor projectDescriptor in projectDescriptors) { foreach (ProjectDescriptor projectDescriptor in projectDescriptors) {
IProject newProject = projectDescriptor.CreateProject(projectCreateInformation, defaultLanguage); IProject newProject = projectDescriptor.CreateProject(projectCreateInformation, defaultLanguage);
if (newProject != null) { if (newProject == null)
newProject.Location = FileUtility.GetRelativePath(oldCombinePath, newProject.FileName); return null;
newCombine.AddFolder(newProject); newProject.Location = FileUtility.GetRelativePath(oldCombinePath, newProject.FileName);
} newCombine.AddFolder(newProject);
projectCreateInformation.CreatedProjects.Add(newProject.FileName); projectCreateInformation.CreatedProjects.Add(newProject.FileName);
} }
@ -92,7 +92,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
projectCreateInformation.CombinePath = oldCombinePath; projectCreateInformation.CombinePath = oldCombinePath;
projectCreateInformation.ProjectBasePath = oldProjectPath; projectCreateInformation.ProjectBasePath = oldProjectPath;
string combineLocation = Path.Combine(projectCreateInformation.CombinePath, newCombineName + ".sln"); string combineLocation = Path.Combine(projectCreateInformation.CombinePath, newCombineName + ".sln");
// Save combine // Save combine
if (File.Exists(combineLocation)) { if (File.Exists(combineLocation)) {

2
src/Main/Base/Project/Src/Internal/Templates/Project/ProjectDescriptor.cs

@ -78,7 +78,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
string language = languageName != null && languageName.Length > 0 ? languageName : defaultLanguage; string language = languageName != null && languageName.Length > 0 ? languageName : defaultLanguage;
LanguageBindingDescriptor descriptor = LanguageBindingService.GetCodonPerLanguageName(language); LanguageBindingDescriptor descriptor = LanguageBindingService.GetCodonPerLanguageName(language);
ILanguageBinding languageinfo = descriptor.Binding; ILanguageBinding languageinfo = (descriptor != null) ? descriptor.Binding : null;
if (languageinfo == null) { if (languageinfo == null) {
StringParser.Properties["type"] = language; StringParser.Properties["type"] = language;

33
src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentEnumerator.cs

@ -16,8 +16,15 @@ using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Project namespace ICSharpCode.SharpDevelop.Project
{ {
/// <summary> /// <summary>
/// Description of ParseableFileContentEnumerator. /// An enumerator which enumerates through a list of project items, returning the
/// parseable file content of each item.
/// </summary> /// </summary>
/// <remarks>
/// This class is thread-safe in a very limited way:
/// It can be created from every thread, but may be only used by the thread that created it.
/// It automatically uses WorkbenchSingleton.SafeThreadCall for reading currently open
/// files when it is created/accessed from a thread.
/// </remarks>
public class ParseableFileContentEnumerator : IEnumerator<KeyValuePair<string, string>> public class ParseableFileContentEnumerator : IEnumerator<KeyValuePair<string, string>>
{ {
void IEnumerator.Reset() { void IEnumerator.Reset() {
@ -55,11 +62,13 @@ namespace ICSharpCode.SharpDevelop.Project
} }
ProjectItem[] projectItems; ProjectItem[] projectItems;
bool isOnMainThread;
public ParseableFileContentEnumerator(IProject project) : this(project.Items.ToArray()) { } public ParseableFileContentEnumerator(IProject project) : this(project.Items.ToArray()) { }
public ParseableFileContentEnumerator(ProjectItem[] projectItems) public ParseableFileContentEnumerator(ProjectItem[] projectItems)
{ {
isOnMainThread = !WorkbenchSingleton.InvokeRequired;
this.projectItems = projectItems; this.projectItems = projectItems;
Properties textEditorProperties = ((Properties)PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties())); Properties textEditorProperties = ((Properties)PropertyService.Get("ICSharpCode.TextEditor.Document.Document.DefaultDocumentAggregatorProperties", new Properties()));
getParseableContentEncoding = Encoding.GetEncoding(textEditorProperties.Get("Encoding", 1252)); getParseableContentEncoding = Encoding.GetEncoding(textEditorProperties.Get("Encoding", 1252));
@ -77,8 +86,6 @@ namespace ICSharpCode.SharpDevelop.Project
string GetParseableFileContent(IProject project, string fileName) string GetParseableFileContent(IProject project, string fileName)
{ {
//Console.WriteLine("Reading {0} from disk", fileName);
// Loading the source files is done asynchronously: // Loading the source files is done asynchronously:
// While one file is parsed, the next is already loaded from disk. // While one file is parsed, the next is already loaded from disk.
string res = project.GetParseableFileContent(fileName); string res = project.GetParseableFileContent(fileName);
@ -141,21 +148,35 @@ namespace ICSharpCode.SharpDevelop.Project
string GetFileContent(ProjectItem item) string GetFileContent(ProjectItem item)
{ {
string fileName = item.FileName; string fileName = item.FileName;
string content;
if (isOnMainThread)
content = GetFileContentFromOpenFile(fileName);
else
content = (string)WorkbenchSingleton.SafeThreadCall(this, "GetFileContentFromOpenFile", fileName);
if (content != null)
return content;
return GetParseableFileContent(item.Project, fileName);
}
string GetFileContentFromOpenFile(string fileName)
{
IWorkbenchWindow window = FileService.GetOpenFile(fileName); IWorkbenchWindow window = FileService.GetOpenFile(fileName);
if (window != null) { if (window != null) {
IViewContent viewContent = window.ViewContent; IViewContent viewContent = window.ViewContent;
IEditable editable = viewContent as IEditable; IEditable editable = viewContent as IEditable;
if (editable != null) { if (editable != null) {
//Console.WriteLine("Reading {0} from editable", fileName);
return editable.Text; return editable.Text;
} }
} }
return GetParseableFileContent(item.Project, fileName); return null;
} }
bool CanReadAsync(ProjectItem item) bool CanReadAsync(ProjectItem item)
{ {
return !FileService.IsOpen(item.FileName); if (isOnMainThread)
return !FileService.IsOpen(item.FileName);
else
return !(bool)WorkbenchSingleton.SafeThreadCall(typeof(FileService), "IsOpen", item.FileName);
} }
} }
} }

8
src/Main/Base/Project/Src/TextEditor/Gui/Editor/TextEditorDisplayBinding.cs

@ -429,18 +429,14 @@ namespace ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor
} }
} }
delegate void ParseInformationDelegate(ParseInformation parseInfo);
public void ParseInformationUpdated(ParseInformation parseInfo) public void ParseInformationUpdated(ParseInformation parseInfo)
{ {
if (textAreaControl.TextEditorProperties.EnableFolding) { if (textAreaControl.TextEditorProperties.EnableFolding) {
TextArea textArea = textAreaControl.ActiveTextAreaControl.TextArea; WorkbenchSingleton.SafeThreadAsyncCall(this, "ParseInformationUpdatedInvoked", parseInfo);
if (textArea.IsHandleCreated)
textArea.Invoke(new ParseInformationDelegate(ParseInformationUpdatedInternal), new object[] { parseInfo });
} }
} }
void ParseInformationUpdatedInternal(ParseInformation parseInfo) void ParseInformationUpdatedInvoked(ParseInformation parseInfo)
{ {
try { try {
textAreaControl.Document.FoldingManager.UpdateFoldings(TitleName, parseInfo); textAreaControl.Document.FoldingManager.UpdateFoldings(TitleName, parseInfo);

Loading…
Cancel
Save