Browse Source

Fixed SD2-1602: Order of nodes in AddIn tree path is not preserved.

Fixed ArgumentNullException in TaskListPad / ParserService.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5239 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
pull/1/head
Daniel Grunwald 16 years ago
parent
commit
49f8c18d14
  1. 22
      src/AddIns/DisplayBindings/XmlEditor/Test/Editor/DefaultSchemaFileAssociationsTestFixture.cs
  2. 5
      src/AddIns/DisplayBindings/XmlEditor/Test/Editor/DefaultXmlEditorOptionsTestFixture.cs
  3. 8
      src/AddIns/DisplayBindings/XmlEditor/Test/Editor/XmlEditorFileExtensionsTestFixture.cs
  4. 4
      src/AddIns/Misc/ResourceToolkit/Project/Hornung.ResourceToolkit.addin
  5. 5
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Properties/AssemblyInfo.cs
  6. 4
      src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs
  7. 1
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  8. 913
      src/Main/Base/Project/Src/Services/ParserService/OldParserService.cs
  9. 6
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  10. 2
      src/Main/Core/Project/Configuration/AssemblyInfo.cs
  11. 4
      src/Main/Core/Project/ICSharpCode.Core.csproj
  12. 12
      src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs
  13. 4
      src/Main/Core/Project/Src/AddInTree/AddInTree.cs
  14. 121
      src/Main/Core/Project/Src/AddInTree/AddInTreeNode.cs
  15. 87
      src/Main/Core/Project/Src/AddInTree/TopologicalSort.cs
  16. 6
      src/Main/Core/Test/AssemblyInfo.cs
  17. 7
      src/Main/Core/Test/ICSharpCode.Core.Tests.csproj
  18. 39
      src/Main/Core/Test/TopologicalSortTest.cs
  19. 3
      src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/RefactoringProvider.cs

22
src/AddIns/DisplayBindings/XmlEditor/Test/Editor/DefaultSchemaFileAssociationsTestFixture.cs

@ -34,16 +34,20 @@ namespace XmlEditor.Tests.Editor @@ -34,16 +34,20 @@ namespace XmlEditor.Tests.Editor
AddInTreeNode addinTreeNode = new AddInTreeNode();
Properties properties = new Properties();
properties.Set<string>("id", ".xml");
properties.Set<string>("namespaceUri", "http://example.com");
addinTreeNode.Codons.Add(new Codon(addin, "SchemaAssociation", properties, new ICondition[0]));
Properties properties1 = new Properties();
properties1.Set<string>("id", ".xml");
properties1.Set<string>("namespaceUri", "http://example.com");
properties = new Properties();
properties.Set<string>("id", ".xsl");
properties.Set<string>("namespaceUri", "http://example.com/xsl");
properties.Set<string>("namespacePrefix", "xs");
addinTreeNode.Codons.Add(new Codon(addin, "SchemaAssociation", properties, new ICondition[0]));
Properties properties2 = new Properties();
properties2.Set<string>("id", ".xsl");
properties2.Set<string>("namespaceUri", "http://example.com/xsl");
properties2.Set<string>("namespacePrefix", "xs");
addinTreeNode.AddCodons(
new Codon[] {
new Codon(addin, "SchemaAssociation", properties1, new ICondition[0]),
new Codon(addin, "SchemaAssociation", properties2, new ICondition[0])
});
schemaAssociations = new DefaultXmlSchemaFileAssociations(addinTreeNode);
}

5
src/AddIns/DisplayBindings/XmlEditor/Test/Editor/DefaultXmlEditorOptionsTestFixture.cs

@ -51,7 +51,10 @@ namespace XmlEditor.Tests.Editor @@ -51,7 +51,10 @@ namespace XmlEditor.Tests.Editor
properties.Set<string>("id", ".xml");
properties.Set<string>("namespaceUri", "http://example.com");
properties.Set<string>("namespacePrefix", "e");
addinTreeNode.Codons.Add(new Codon(addin, "SchemaAssociation", properties, new ICondition[0]));
addinTreeNode.AddCodons(
new Codon[] {
new Codon(addin, "SchemaAssociation", properties, new ICondition[0])
});
return new DefaultXmlSchemaFileAssociations(addinTreeNode);
}

8
src/AddIns/DisplayBindings/XmlEditor/Test/Editor/XmlEditorFileExtensionsTestFixture.cs

@ -33,12 +33,16 @@ namespace XmlEditor.Tests.Editor @@ -33,12 +33,16 @@ namespace XmlEditor.Tests.Editor
AddIn addin = AddIn.Load(reader);
AddInTreeNode addinTreeNode = new AddInTreeNode();
addinTreeNode.Codons.Add(new Codon(addin, "CodeCompletionC#", new Properties(), new ICondition[0]));
Properties properties = new Properties();
properties.Set<string>("extensions", " .xml; .xsd ");
properties.Set<string>("id", "Xml");
addinTreeNode.Codons.Add(new Codon(addin, "CodeCompletionXml", properties, new ICondition[0]));
addinTreeNode.AddCodons(
new Codon[] {
new Codon(addin, "CodeCompletionC#", new Properties(), new ICondition[0]),
new Codon(addin, "CodeCompletionXml", properties, new ICondition[0])
});
fileExtensions = new DefaultXmlFileExtensions(addinTreeNode);
}

4
src/AddIns/Misc/ResourceToolkit/Project/Hornung.ResourceToolkit.addin

@ -42,10 +42,6 @@ @@ -42,10 +42,6 @@
<MenuItem id = "StringResources" insertbefore = "Refactoring" type = "Builder" class = "Hornung.ResourceToolkit.Commands.TextEditorContextMenuBuilder" />
</Path>
<Path name = "/SharpDevelop/ViewContent/XmlEditor/ContextMenu">
<Include id = "StringResources" item = "/SharpDevelop/ViewContent/DefaultTextEditor/ContextMenu/StringResources" insertbefore = "Cut" />
</Path>
<!-- Tools menu -->
<Path name="/Workspace/Tools">

5
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit.Tests/Properties/AssemblyInfo.cs

@ -9,12 +9,11 @@ using System.Runtime.InteropServices; @@ -9,12 +9,11 @@ using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("ICSharpCode.CodeEditor.Tests")]
[assembly: AssemblyTitle("ICSharpCode.AvalonEdit.Tests")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ICSharpCode.CodeEditor.Tests")]
[assembly: AssemblyCopyright("Copyright 2008")]
[assembly: AssemblyProduct("ICSharpCode.AvalonEdit.Tests")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

4
src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/VisualLine.cs

@ -117,8 +117,8 @@ namespace ICSharpCode.AvalonEdit.Rendering @@ -117,8 +117,8 @@ namespace ICSharpCode.AvalonEdit.Rendering
elements.Add(new VisualLineText(this, textPieceLength));
offset = textPieceEndOffset;
}
// if no elements constructed / only zero-length elements constructed:
// prevent endless loop by asking the generators again for the same location
// If no elements constructed / only zero-length elements constructed:
// do not asking the generators again for the same location (would cause endless loop)
askInterestOffset = 1;
foreach (VisualLineElementGenerator g in generators) {
if (g.cachedInterest == offset) {

1
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -285,7 +285,6 @@ @@ -285,7 +285,6 @@
<Resource Include="Src\Services\Debugger\Tooltips\magnifier.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<None Include="Src\Services\ParserService\OldParserService.cs" />
<Compile Include="Src\Services\DisplayBinding\DisplayBindingDoozer.cs" />
<Compile Include="Src\Internal\ConditionEvaluators\CombineOpenEvaluator.cs" />
<Compile Include="Src\Services\ProjectBinding\ProjectBindingDoozer.cs" />

913
src/Main/Base/Project/Src/Services/ParserService/OldParserService.cs

@ -1,913 +0,0 @@ @@ -1,913 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
// <version>$Revision$</version>
// </file>
using ICSharpCode.SharpDevelop.Editor;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.DefaultEditor.Gui.Editor;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop.Dom.Refactoring;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
using RegistryContentPair = System.Collections.Generic.KeyValuePair<ICSharpCode.SharpDevelop.Dom.ProjectContentRegistry, ICSharpCode.SharpDevelop.Dom.IProjectContent>;
namespace ICSharpCode.SharpDevelop
{
public static class OldParserService
{
static IList<ParserDescriptor> parser;
static IList<ProjectContentRegistryDescriptor> registries;
static Dictionary<IProject, IProjectContent> projectContents = new Dictionary<IProject, IProjectContent>();
static Dictionary<string, ParseInformation> parsings = new Dictionary<string, ParseInformation>(StringComparer.OrdinalIgnoreCase);
static ProjectContentRegistry defaultProjectContentRegistry = new ProjectContentRegistry();
static string domPersistencePath;
internal static void InitializeParserService()
{
if (parser == null) {
parser = AddInTree.BuildItems<ParserDescriptor>("/Workspace/Parser", null, false);
registries = AddInTree.BuildItems<ProjectContentRegistryDescriptor>("/Workspace/ProjectContentRegistry", null, false);
if (!string.IsNullOrEmpty(domPersistencePath)) {
Directory.CreateDirectory(domPersistencePath);
defaultProjectContentRegistry.ActivatePersistence(domPersistencePath);
}
ProjectService.SolutionClosed += ProjectServiceSolutionClosed;
}
}
/// <summary>
/// Gets/Sets the cache directory used for DOM persistence.
/// </summary>
public static string DomPersistencePath {
get {
return domPersistencePath;
}
set {
if (parser != null)
throw new InvalidOperationException("Cannot set DomPersistencePath after ParserService was initialized");
domPersistencePath = value;
}
}
public static ProjectContentRegistry DefaultProjectContentRegistry {
get {
return defaultProjectContentRegistry;
}
}
public static IProjectContent CurrentProjectContent {
[DebuggerStepThrough]
get {
if (ProjectService.CurrentProject == null || !projectContents.ContainsKey(ProjectService.CurrentProject)) {
return DefaultProjectContent;
}
return projectContents[ProjectService.CurrentProject];
}
}
/// <summary>
/// Gets the list of project contents of all open projects. Does not include assembly project contents.
/// </summary>
public static IEnumerable<IProjectContent> AllProjectContents {
get {
return projectContents.Values;
}
}
static void ProjectServiceSolutionClosed(object sender, EventArgs e)
{
abortLoadSolutionProjectsThread = true;
lock (reParse1) { // clear queue of reparse thread
reParse1.Clear();
reParse2.Clear();
}
lock (projectContents) {
foreach (IProjectContent content in projectContents.Values) {
content.Dispose();
}
projectContents.Clear();
}
lock (parsings) {
parsings.Clear();
}
lock (parseQueue) {
parseQueue.Clear();
}
lastUpdateHash.Clear();
}
static Thread loadSolutionProjectsThread;
static bool abortLoadSolutionProjectsThread;
// do not use an event for this because a solution might be loaded before ParserService
// is initialized
internal static void OnSolutionLoaded()
{
if (loadSolutionProjectsThread != null) {
if (!abortLoadSolutionProjectsThread)
throw new InvalidOperationException("Cannot open new solution without closing old solution!");
if (!loadSolutionProjectsThread.Join(50)) {
// loadSolutionProjects might be waiting for main thread, so give it
// a chance to complete safethread calls by putting this method at
// the end of the invoking queue
WorkbenchSingleton.SafeThreadAsyncCall(OnSolutionLoaded);
return;
}
}
loadSolutionProjectsThread = new Thread(new ThreadStart(LoadSolutionProjects));
loadSolutionProjectsThread.Name = "loadSolutionProjects";
loadSolutionProjectsThread.Priority = ThreadPriority.BelowNormal;
loadSolutionProjectsThread.IsBackground = true;
loadSolutionProjectsThread.Start();
}
public static bool LoadSolutionProjectsThreadRunning {
get {
return loadSolutionProjectsThread != null;
}
}
static void LoadSolutionProjects()
{
try {
abortLoadSolutionProjectsThread = false;
LoggingService.Info("Start LoadSolutionProjects thread");
LoadSolutionProjectsInternal();
} finally {
LoggingService.Info("LoadSolutionProjects thread ended");
loadSolutionProjectsThread = null;
OnLoadSolutionProjectsThreadEnded(EventArgs.Empty);
}
}
static void LoadSolutionProjectsInternal()
{
IProgressMonitor progressMonitor = StatusBarService.CreateProgressMonitor();
List<ParseProjectContent> createdContents = new List<ParseProjectContent>();
foreach (IProject project in ProjectService.OpenSolution.Projects) {
try {
ParseProjectContent newContent = project.CreateProjectContent();
if (newContent != null) {
lock (projectContents) {
projectContents[project] = newContent;
}
createdContents.Add(newContent);
}
} catch (Exception e) {
MessageService.ShowException(e, "Error while retrieving project contents from " + project);
}
}
WorkbenchSingleton.SafeThreadAsyncCall(ProjectService.ParserServiceCreatedProjectContents);
try {
int workAmount = 0;
// multiply Count with 2 so that the progress bar is only at 50% when references are done
progressMonitor.BeginTask("Loading references...", createdContents.Count * 2, false);
for (int i = 0; i < createdContents.Count; i++) {
if (abortLoadSolutionProjectsThread) return;
ParseProjectContent newContent = createdContents[i];
progressMonitor.WorkDone = i;
try {
newContent.Initialize1(progressMonitor);
workAmount += newContent.GetInitializationWorkAmount();
} catch (Exception e) {
MessageService.ShowException(e, "Error while initializing project references:" + newContent);
}
}
// multiply workamount with two and start at workAmount so that the progress bar continues
// from 50% towards 100%.
progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount * 2, false);
progressMonitor.WorkDone = workAmount;
foreach (ParseProjectContent newContent in createdContents) {
if (abortLoadSolutionProjectsThread) return;
try {
newContent.Initialize2(progressMonitor);
} catch (Exception e) {
MessageService.ShowException(e, "Error while initializing project contents:" + newContent);
}
}
} finally {
progressMonitor.Done();
}
}
static void InitAddedProject(object state)
{
ParseProjectContent newContent = (ParseProjectContent)state;
IProgressMonitor progressMonitor = StatusBarService.CreateProgressMonitor();
newContent.Initialize1(progressMonitor);
progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", newContent.GetInitializationWorkAmount(), false);
newContent.Initialize2(progressMonitor);
progressMonitor.Done();
}
#region Reparse projects
// queue of projects waiting to reparse references
static Queue<ParseProjectContent> reParse1 = new Queue<ParseProjectContent>();
// queue of projects waiting to reparse code
static Queue<ParseProjectContent> reParse2 = new Queue<ParseProjectContent>();
static Thread reParseThread;
static void ReparseProjects()
{
LoggingService.Info("reParse thread started");
Thread.Sleep(100); // enable main thread to fill the queues completely
try {
ReparseProjectsInternal();
} catch (Exception ex) {
MessageService.ShowException(ex);
}
}
static void ReparseProjectsInternal()
{
bool parsing = false;
ParseProjectContent job;
IProgressMonitor progressMonitor = StatusBarService.CreateProgressMonitor();
while (true) {
// get next job
lock (reParse1) {
if (reParse1.Count > 0) {
if (parsing) {
progressMonitor.Done();
}
parsing = false;
job = reParse1.Dequeue();
} else if (reParse2.Count > 0) {
if (!parsing) {
int workAmount = 0;
foreach (ParseProjectContent ppc in reParse2) {
workAmount += ppc.GetInitializationWorkAmount();
}
progressMonitor.BeginTask("${res:ICSharpCode.SharpDevelop.Internal.ParserService.Parsing}...", workAmount, false);
}
parsing = true;
job = reParse2.Dequeue();
} else {
// all jobs done
reParseThread = null;
if (parsing) {
progressMonitor.Done();
}
LoggingService.Info("reParse thread finished all jobs");
return;
}
}
// execute job
if (parsing) {
LoggingService.Info("reparsing code for " + job.Project);
job.ReInitialize2(progressMonitor);
} else {
LoggingService.Debug("reloading references for " + job.Project);
job.ReInitialize1(progressMonitor);
}
}
}
public static void Reparse(IProject project, bool initReferences, bool parseCode)
{
ParseProjectContent pc = GetProjectContent(project) as ParseProjectContent;
if (pc != null) {
lock (reParse1) {
if (initReferences && !reParse1.Contains(pc)) {
LoggingService.Debug("Enqueue for reinitializing references: " + project);
reParse1.Enqueue(pc);
}
if (parseCode && !reParse2.Contains(pc)) {
LoggingService.Debug("Enqueue for reparsing code: " + project);
reParse2.Enqueue(pc);
}
if (reParseThread == null) {
LoggingService.Info("Starting reParse thread");
reParseThread = new Thread(new ThreadStart(ReparseProjects));
reParseThread.Name = "reParse";
reParseThread.Priority = ThreadPriority.BelowNormal;
reParseThread.IsBackground = true;
reParseThread.Start();
}
}
}
}
#endregion
/// <remarks>Can return null.</remarks>
internal static IProjectContent CreateProjectContentForAddedProject(IProject project)
{
lock (projectContents) {
ParseProjectContent newContent = project.CreateProjectContent();
if (newContent != null) {
projectContents[project] = newContent;
ThreadPool.QueueUserWorkItem(InitAddedProject, newContent);
}
return newContent;
}
}
internal static void RemoveProjectContentForRemovedProject(IProject project)
{
lock (projectContents) {
projectContents.Remove(project);
}
}
public static IProjectContent GetProjectContent(IProject project)
{
lock (projectContents) {
if (projectContents.ContainsKey(project)) {
return projectContents[project];
}
}
return null;
}
static Queue<KeyValuePair<string, ITextBuffer>> parseQueue = new Queue<KeyValuePair<string, ITextBuffer>>();
static void ParseQueue()
{
while (true) {
KeyValuePair<string, ITextBuffer> entry;
lock (parseQueue) {
if (parseQueue.Count == 0)
return;
entry = parseQueue.Dequeue();
}
ParseFile(entry.Key, entry.Value);
}
}
public static void EnqueueForParsing(string fileName)
{
EnqueueForParsing(fileName, GetParseableFileContent(fileName));
}
public static void EnqueueForParsing(string fileName, ITextBuffer fileContent)
{
fileContent = fileContent.CreateSnapshot();
lock (parseQueue) {
parseQueue.Enqueue(new KeyValuePair<string, ITextBuffer>(fileName, fileContent));
}
}
public static void StartParserThread()
{
abortParserUpdateThread = false;
Thread parserThread = new Thread(new ThreadStart(ParserUpdateThread));
parserThread.Name = "parser";
parserThread.Priority = ThreadPriority.BelowNormal;
parserThread.IsBackground = true;
parserThread.Start();
}
public static void StopParserThread()
{
abortParserUpdateThread = true;
}
static volatile bool abortParserUpdateThread = false;
static Dictionary<string, int> lastUpdateHash = new Dictionary<string, int>();
static void ParserUpdateThread()
{
LoggingService.Info("ParserUpdateThread started");
Thread.Sleep(750);
// preload mscorlib, we're going to need it probably
IProjectContent dummyVar = defaultProjectContentRegistry.Mscorlib;
while (!abortParserUpdateThread) {
try {
ParseQueue();
ParserUpdateStep();
} catch (Exception e) {
ICSharpCode.Core.MessageService.ShowException(e);
// don't fire an exception every 2 seconds at the user, give him at least
// time to read the first :-)
Thread.Sleep(10000);
}
Thread.Sleep(2000);
}
LoggingService.Info("ParserUpdateThread stopped");
}
public static void ParseCurrentViewContent()
{
ParserUpdateStep();
}
static void ParserUpdateStep()
{
IViewContent activeViewContent = null;
string fileName = null;
bool isUntitled = false;
try {
WorkbenchSingleton.SafeThreadCall(
delegate {
try {
activeViewContent = WorkbenchSingleton.Workbench.ActiveViewContent;
if (activeViewContent != null && activeViewContent.PrimaryFile != null) {
fileName = activeViewContent.PrimaryFileName;
isUntitled = activeViewContent.PrimaryFile.IsUntitled;
}
} catch (Exception ex) {
MessageService.ShowError(ex.ToString());
}
});
} catch (InvalidOperationException ex) { // includes ObjectDisposedException
// maybe workbench has been disposed while waiting for the SafeThreadCall
// can occur after workbench unload or after aborting SharpDevelop with
// Application.Exit()
LoggingService.Warn("InvalidOperationException while trying to invoke GetActiveViewContent() " + ex);
return; // abort this thread
}
IEditable editable = activeViewContent as IEditable;
if (editable != null) {
if (!(fileName == null || fileName.Length == 0)) {
ParseInformation parseInformation = null;
bool updated = false;
ITextBuffer fileContent = editable.CreateSnapshot();
if (fileContent == null) return;
parseInformation = ParseFile(fileName, fileContent, !isUntitled);
updated = true;
if (updated) {
if (parseInformation != null && editable is IParseInformationListener) {
((IParseInformationListener)editable).ParseInformationUpdated(parseInformation);
}
}
OnParserUpdateStepFinished(new ParserUpdateStepEventArgs(fileName, fileContent, updated, parseInformation));
}
}
}
public static void ParseViewContent(IViewContent viewContent)
{
ITextBuffer text = ((IEditable)viewContent).CreateSnapshot();
ParseInformation parseInformation = ParseFile(viewContent.PrimaryFileName,
text, !viewContent.PrimaryFile.IsUntitled);
if (parseInformation != null && viewContent is IParseInformationListener) {
((IParseInformationListener)viewContent).ParseInformationUpdated(parseInformation);
}
}
/// <summary>
/// <para>This event is called every two seconds. It is called directly after the parser has updated the
/// project content and it is called after the parser noticed that there is nothing to update.</para>
/// <para><b>WARNING: This event is called on the parser thread - You need to use Invoke if you do
/// anything in your event handler that could touch the GUI.</b></para>
/// </summary>
public static event ParserUpdateStepEventHandler ParserUpdateStepFinished;
static void OnParserUpdateStepFinished(ParserUpdateStepEventArgs e)
{
if (ParserUpdateStepFinished != null) {
ParserUpdateStepFinished(typeof(ParserService), e);
}
}
public static ParseInformation ParseFile(string fileName)
{
return ParseFile(fileName, null);
}
public static ParseInformation ParseFile(string fileName, ITextBuffer fileContent)
{
return ParseFile(fileName, fileContent, true);
}
static IProjectContent GetProjectContent(string fileName)
{
lock (projectContents) {
foreach (KeyValuePair<IProject, IProjectContent> projectContent in projectContents) {
if (projectContent.Key.IsFileInProject(fileName)) {
return projectContent.Value;
}
}
}
return null;
}
static DefaultProjectContent defaultProjectContent;
public static IProjectContent DefaultProjectContent {
get {
if (defaultProjectContent == null) {
lock (projectContents) {
if (defaultProjectContent == null) {
CreateDefaultProjectContent();
}
}
}
return defaultProjectContent;
}
}
static void CreateDefaultProjectContent()
{
LoggingService.Info("Creating default project content");
//LoggingService.Debug("Stacktrace is:\n" + Environment.StackTrace);
defaultProjectContent = new DefaultProjectContent();
defaultProjectContent.AddReferencedContent(defaultProjectContentRegistry.Mscorlib);
Thread t = new Thread(new ThreadStart(CreateDefaultProjectContentReferences));
t.IsBackground = true;
t.Priority = ThreadPriority.BelowNormal;
t.Name = "CreateDefaultPC";
t.Start();
}
static void CreateDefaultProjectContentReferences()
{
IList<string> defaultReferences = AddInTree.BuildItems<string>("/SharpDevelop/Services/ParserService/SingleFileGacReferences", null, false);
foreach (string defaultReference in defaultReferences) {
ReferenceProjectItem item = new ReferenceProjectItem(null, defaultReference);
defaultProjectContent.AddReferencedContent(ParserService.GetProjectContentForReference(item));
}
if (WorkbenchSingleton.Workbench != null) {
WorkbenchSingleton.Workbench.ActiveViewContentChanged += delegate {
if (WorkbenchSingleton.Workbench.ActiveViewContent != null) {
string file = WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName;
if (file != null) {
IParser parser = GetParser(file);
if (parser != null && parser.Language != null) {
defaultProjectContent.Language = parser.Language;
defaultProjectContent.DefaultImports = parser.Language.CreateDefaultImports(defaultProjectContent);
}
}
}
};
}
}
public static ParseInformation ParseFile(string fileName, ITextBuffer fileContent, bool updateCommentTags)
{
return ParseFile(null, fileName, fileContent, updateCommentTags);
}
public static ParseInformation ParseFile(IProjectContent fileProjectContent, string fileName, ITextBuffer fileContent, bool updateCommentTags)
{
if (fileName == null) throw new ArgumentNullException("fileName");
IParser parser = GetParser(fileName);
if (parser == null) {
return null;
}
ICompilationUnit parserOutput = null;
try {
if (fileProjectContent == null) {
// GetProjectContent is expensive because it compares all file names, so
// we accept the project content as optional parameter.
fileProjectContent = GetProjectContent(fileName);
if (fileProjectContent == null) {
fileProjectContent = DefaultProjectContent;
}
}
if (fileContent == null) {
if (!File.Exists(fileName)) {
return null;
}
fileContent = GetParseableFileContent(fileName);
}
parserOutput = parser.Parse(fileProjectContent, fileName, fileContent);
parserOutput.Freeze();
ParseInformation parseInformation;
lock (parsings) {
if (!parsings.TryGetValue(fileName, out parseInformation)) {
parsings[fileName] = parseInformation = new ParseInformation();
}
}
ICompilationUnit oldUnit = parseInformation.MostRecentCompilationUnit;
fileProjectContent.UpdateCompilationUnit(oldUnit, parserOutput, fileName);
parseInformation.SetCompilationUnit(parserOutput);
if (updateCommentTags) {
TaskService.UpdateCommentTags(fileName, parserOutput.TagComments);
}
try {
OnParseInformationUpdated(new ParseInformationEventArgs(fileName, fileProjectContent, oldUnit, parserOutput));
} catch (Exception e) {
MessageService.ShowException(e);
}
return parseInformation;
} catch (Exception e) {
MessageService.ShowException(e, "Error parsing " + fileName);
}
return null;
}
/// <summary>
/// Gets the content of the file using encoding auto-detection (or DefaultFileEncoding, if that fails).
/// If the file is already open, gets the text in the opened view content.
/// </summary>
public static ITextBuffer GetParseableFileContent(string fileName)
{
IViewContent viewContent = FileService.GetOpenFile(fileName);
IEditable editable = viewContent as IEditable;
if (editable != null) {
return editable.CreateSnapshot();
}
//ITextBuffer res = project.GetParseableFileContent(fileName);
//if (res != null)
// return res;
OpenedFile file = FileService.GetOpenedFile(fileName);
if (file != null) {
IFileDocumentProvider p = file.CurrentView as IFileDocumentProvider;
if (p != null) {
IDocument document = p.GetDocumentForFile(file);
if (document != null) {
return document.CreateSnapshot();
}
}
using(Stream s = file.OpenRead()) {
// load file
Encoding encoding = DefaultFileEncoding;
return new StringTextBuffer(ICSharpCode.TextEditor.Util.FileReader.ReadFileContent(s, ref encoding));
}
}
// load file
return new StringTextBuffer(ICSharpCode.TextEditor.Util.FileReader.ReadFileContent(fileName, DefaultFileEncoding));
}
public static Encoding DefaultFileEncoding {
get {
return DefaultEditor.Gui.Editor.SharpDevelopTextEditorProperties.Instance.Encoding;
}
}
public static ParseInformation GetParseInformation(string fileName)
{
if (fileName == null || fileName.Length == 0) {
return null;
}
ParseInformation parseInfo;
lock (parsings) {
if (parsings.TryGetValue(fileName, out parseInfo))
return parseInfo;
}
return ParseFile(fileName);
}
/// <summary>
/// Registers a compilation unit in the parser service.
/// Does not fire the OnParseInformationUpdated event, please use this for unit tests only!
/// </summary>
public static ParseInformation RegisterParseInformation(string fileName, ICompilationUnit cu)
{
ParseInformation parseInformation;
lock (parsings) {
if (!parsings.TryGetValue(fileName, out parseInformation)) {
parsings[fileName] = parseInformation = new ParseInformation();
}
}
parseInformation.SetCompilationUnit(cu);
return parseInformation;
}
public static void ClearParseInformation(string fileName)
{
if (fileName == null || fileName.Length == 0) {
return;
}
LoggingService.Info("ClearParseInformation: " + fileName);
ParseInformation parseInfo;
lock (parsings) {
if (parsings.TryGetValue(fileName, out parseInfo))
parsings.Remove(fileName);
else
return;
}
ICompilationUnit oldUnit = parseInfo.MostRecentCompilationUnit;
if (oldUnit != null) {
IProjectContent pc = parseInfo.MostRecentCompilationUnit.ProjectContent;
pc.RemoveCompilationUnit(oldUnit);
try {
OnParseInformationUpdated(new ParseInformationEventArgs(fileName, pc, oldUnit, null));
} catch (Exception e) {
MessageService.ShowException(e);
}
}
}
public static IExpressionFinder GetExpressionFinder(string fileName)
{
IParser parser = GetParser(fileName);
if (parser != null) {
return parser.CreateExpressionFinder(fileName);
}
return null;
}
public static readonly string[] DefaultTaskListTokens = {"HACK", "TODO", "UNDONE", "FIXME"};
/// <summary>
/// Retrieves the IParser instance that can parse the specified file.
/// This method is thread-safe.
/// </summary>
public static IParser GetParser(string fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
IParser curParser = null;
foreach (ParserDescriptor descriptor in parser) {
if (descriptor.CanParse(fileName)) {
curParser = descriptor.Parser;
break;
}
}
if (curParser != null) {
curParser.LexerTags = PropertyService.Get("SharpDevelop.TaskListTokens", DefaultTaskListTokens);
}
return curParser;
}
////////////////////////////////////
public static ArrayList CtrlSpace(int caretLine, int caretColumn,
string fileName, string fileContent, ExpressionContext context)
{
IResolver resolver = CreateResolver(fileName);
if (resolver != null) {
return resolver.CtrlSpace(caretLine, caretColumn, GetParseInformation(fileName), fileContent, context);
}
return null;
}
public static IResolver CreateResolver(string fileName)
{
IParser parser = GetParser(fileName);
if (parser != null) {
return parser.CreateResolver();
}
return null;
}
public static ResolveResult Resolve(ExpressionResult expressionResult,
int caretLineNumber, int caretColumn,
string fileName, string fileContent)
{
if (expressionResult.Region.IsEmpty) {
expressionResult.Region = new DomRegion(caretLineNumber, caretColumn);
}
IResolver resolver = CreateResolver(fileName);
if (resolver != null) {
ParseInformation parseInfo = GetParseInformation(fileName);
return resolver.Resolve(expressionResult, parseInfo, fileContent);
}
return null;
}
static void OnParseInformationUpdated(ParseInformationEventArgs e)
{
ParseInformationEventHandler handler = ParseInformationUpdated;
if (handler != null) {
handler(null, e);
}
}
static void OnLoadSolutionProjectsThreadEnded(EventArgs e)
{
EventHandler handler = LoadSolutionProjectsThreadEnded;
if (handler != null) {
handler(null, e);
}
}
public static event EventHandler<ParseInformationEventArgs> ParseInformationUpdated = delegate {};
public static event EventHandler LoadSolutionProjectsThreadEnded;
public static ProjectContentRegistry GetRegistryForReference(ReferenceProjectItem item)
{
if (item is ProjectReferenceProjectItem || item.Project == null) {
return defaultProjectContentRegistry;
}
foreach (ProjectContentRegistryDescriptor registry in registries) {
if (registry.UseRegistryForProject(item.Project)) {
ProjectContentRegistry r = registry.Registry;
if (r != null) {
return r;
} else {
return defaultProjectContentRegistry; // fallback when registry class not found
}
}
}
return defaultProjectContentRegistry;
}
public static IProjectContent GetExistingProjectContentForReference(ReferenceProjectItem item)
{
if (item is ProjectReferenceProjectItem) {
if (((ProjectReferenceProjectItem)item).ReferencedProject == null)
{
return null;
}
return ParserService.GetProjectContent(((ProjectReferenceProjectItem)item).ReferencedProject);
}
return GetRegistryForReference(item).GetExistingProjectContent(item.FileName);
}
public static IProjectContent GetProjectContentForReference(ReferenceProjectItem item)
{
if (item is ProjectReferenceProjectItem) {
if (((ProjectReferenceProjectItem)item).ReferencedProject == null)
{
return null;
}
return ParserService.GetProjectContent(((ProjectReferenceProjectItem)item).ReferencedProject);
}
return GetRegistryForReference(item).GetProjectContentForReference(item.Include, item.FileName);
}
/// <summary>
/// Refreshes the project content for the specified reference if required.
/// This method does nothing if the reference is not an assembly reference, is not loaded or already is up-to-date.
/// </summary>
public static void RefreshProjectContentForReference(ReferenceProjectItem item)
{
if (item is ProjectReferenceProjectItem) {
return;
}
ProjectContentRegistry registry = GetRegistryForReference(item);
registry.RunLocked(
delegate {
IProjectContent rpc = GetExistingProjectContentForReference(item);
if (rpc == null) {
LoggingService.Debug("RefreshProjectContentForReference: not refreshing (rpc==null) " + item.FileName);
return;
}
if (rpc.IsUpToDate) {
LoggingService.Debug("RefreshProjectContentForReference: not refreshing (rpc.IsUpToDate) " + item.FileName);
return;
}
LoggingService.Debug("RefreshProjectContentForReference " + item.FileName);
HashSet<IProject> projectsToRefresh = new HashSet<IProject>();
HashSet<IProjectContent> unloadedReferenceContents = new HashSet<IProjectContent>();
UnloadReferencedContent(projectsToRefresh, unloadedReferenceContents, registry, rpc);
foreach (IProject p in projectsToRefresh) {
Reparse(p, true, false);
}
});
}
static void UnloadReferencedContent(HashSet<IProject> projectsToRefresh, HashSet<IProjectContent> unloadedReferenceContents, ProjectContentRegistry referencedContentRegistry, IProjectContent referencedContent)
{
LoggingService.Debug("Unload referenced content " + referencedContent);
List<RegistryContentPair> otherContentsToUnload = new List<RegistryContentPair>();
foreach (ProjectContentRegistryDescriptor registry in registries) {
if (registry.IsRegistryLoaded) {
foreach (IProjectContent pc in registry.Registry.GetLoadedProjectContents()) {
if (pc.ReferencedContents.Contains(referencedContent)) {
if (unloadedReferenceContents.Add(pc)) {
LoggingService.Debug("Mark dependent content for unloading " + pc);
otherContentsToUnload.Add(new RegistryContentPair(registry.Registry, pc));
}
}
}
}
}
foreach (IProjectContent pc in ParserService.AllProjectContents) {
IProject project = (IProject)pc.Project;
if (projectsToRefresh.Contains(project))
continue;
if (pc.ReferencedContents.Remove(referencedContent)) {
LoggingService.Debug("UnloadReferencedContent: Mark project for reparsing " + project.Name);
projectsToRefresh.Add(project);
}
}
foreach (RegistryContentPair pair in otherContentsToUnload) {
UnloadReferencedContent(projectsToRefresh, unloadedReferenceContents, pair.Key, pair.Value);
}
referencedContentRegistry.UnloadProjectContent(referencedContent);
}
}
}

6
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -532,6 +532,8 @@ namespace ICSharpCode.SharpDevelop @@ -532,6 +532,8 @@ namespace ICSharpCode.SharpDevelop
/// The returned ParseInformation might be stale (re-parse is not forced).</returns>
public static ParseInformation GetParseInformation(string fileName)
{
if (string.IsNullOrEmpty(fileName))
return null;
return GetFileEntry(fileName, true).GetParseInformation(null);
}
@ -542,6 +544,8 @@ namespace ICSharpCode.SharpDevelop @@ -542,6 +544,8 @@ namespace ICSharpCode.SharpDevelop
/// <returns>Returns the ParseInformation for the specified file, or null if the file has not been parsed already.</returns>
public static ParseInformation GetExistingParseInformation(string fileName)
{
if (string.IsNullOrEmpty(fileName))
return null;
FileEntry entry = GetFileEntry(fileName, false);
if (entry != null)
return entry.GetExistingParseInformation(null);
@ -557,6 +561,8 @@ namespace ICSharpCode.SharpDevelop @@ -557,6 +561,8 @@ namespace ICSharpCode.SharpDevelop
/// <returns>Returns the ParseInformation for the specified file, or null if the file has not been parsed for that project content.</returns>
public static ParseInformation GetExistingParseInformation(IProjectContent content, string fileName)
{
if (string.IsNullOrEmpty(fileName))
return null;
FileEntry entry = GetFileEntry(fileName, false);
if (entry != null)
return entry.GetExistingParseInformation(content);

2
src/Main/Core/Project/Configuration/AssemblyInfo.cs

@ -19,3 +19,5 @@ using System.Runtime.CompilerServices; @@ -19,3 +19,5 @@ using System.Runtime.CompilerServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly:InternalsVisibleTo("ICSharpCode.Core.Tests,PublicKey=002400000480000094000000060200000024000052534131000400000100010063D5DB5957250F41969C79E88CBD8806165CA7D96D468A9D60F11704A8B0698684B5ACC16FC82E6CEDE459E1D6ED7384B044C47A67D68BAE1E08182473168E2AD92C6FABE32B9217EA59D05BB9A101318AEEC9F767991D2AE8D987B60C591B6020D2816C395DB7F3045A1C77C2B074C508C2B4F25DCD969688DA94EBC83F5F9B")]

4
src/Main/Core/Project/ICSharpCode.Core.csproj

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@ -83,6 +84,7 @@ @@ -83,6 +84,7 @@
<Compile Include="Src\AddInTree\AddIn\DefaultDoozers\ToolBarItem\ToolBarItemDoozer.cs" />
<Compile Include="Src\AddInTree\AddInTree.cs" />
<Compile Include="Src\AddInTree\AddInTreeNode.cs" />
<Compile Include="Src\AddInTree\TopologicalSort.cs" />
<Compile Include="Src\AddInTree\TreePathNotFoundException.cs" />
<Compile Include="Src\CoreException.cs" />
<Compile Include="Src\Services\AnalyticsMonitor\AnalyticsMonitorService.cs" />

12
src/Main/Core/Project/Src/AddInTree/AddIn/Codon.cs

@ -41,26 +41,14 @@ namespace ICSharpCode.Core @@ -41,26 +41,14 @@ namespace ICSharpCode.Core
public string InsertAfter {
get {
if (!properties.Contains("insertafter")) {
return "";
}
return properties["insertafter"];
}
set {
properties["insertafter"] = value;
}
}
public string InsertBefore {
get {
if (!properties.Contains("insertbefore")) {
return "";
}
return properties["insertbefore"];
}
set {
properties["insertbefore"] = value;
}
}
public string this[string key] {

4
src/Main/Core/Project/Src/AddInTree/AddInTree.cs

@ -225,9 +225,7 @@ namespace ICSharpCode.Core @@ -225,9 +225,7 @@ namespace ICSharpCode.Core
static void AddExtensionPath(ExtensionPath path)
{
AddInTreeNode treePath = CreatePath(rootNode, path.Name);
foreach (Codon codon in path.Codons) {
treePath.Codons.Add(codon);
}
treePath.AddCodons(path.Codons);
}
/// <summary>

121
src/Main/Core/Project/Src/AddInTree/AddInTreeNode.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace ICSharpCode.Core
{
@ -16,9 +17,10 @@ namespace ICSharpCode.Core @@ -16,9 +17,10 @@ namespace ICSharpCode.Core
/// </summary>
public sealed class AddInTreeNode
{
readonly object lockObj = new object();
Dictionary<string, AddInTreeNode> childNodes = new Dictionary<string, AddInTreeNode>();
List<Codon> codons = new List<Codon>();
bool isSorted = false;
ReadOnlyCollection<Codon> codons;
List<ICollection<Codon>> codonInput;
/// <summary>
/// A dictionary containing the child paths.
@ -29,12 +31,36 @@ namespace ICSharpCode.Core @@ -29,12 +31,36 @@ namespace ICSharpCode.Core
}
}
public void AddCodons(ICollection<Codon> newCodons)
{
if (newCodons == null)
throw new ArgumentNullException("newCodons");
lock (lockObj) {
if (codonInput == null) {
codonInput = new List<ICollection<Codon>>();
if (codons != null)
codonInput.Add(codons);
}
codonInput.Add(newCodons);
}
}
/// <summary>
/// A list of child <see cref="Codon"/>s.
/// </summary>
public List<Codon> Codons {
public ReadOnlyCollection<Codon> Codons {
get {
return codons;
lock (lockObj) {
if (codons == null) {
if (codonInput == null) {
codons = new ReadOnlyCollection<Codon>(new Codon[0]);
} else {
codons = TopologicalSort.Sort(codonInput).AsReadOnly();
codonInput = null;
}
}
return codons;
}
}
}
@ -57,92 +83,14 @@ namespace ICSharpCode.Core @@ -57,92 +83,14 @@ namespace ICSharpCode.Core
// }
// }
/// <summary>
/// Supports sorting codons using InsertBefore/InsertAfter
/// </summary>
sealed class TopologicalSort
{
List<Codon> codons;
bool[] visited;
List<Codon> sortedCodons;
Dictionary<string, int> indexOfName;
public TopologicalSort(List<Codon> codons)
{
this.codons = codons;
visited = new bool[codons.Count];
sortedCodons = new List<Codon>(codons.Count);
indexOfName = new Dictionary<string, int>(codons.Count);
// initialize visited to false and fill the indexOfName dictionary
for (int i = 0; i < codons.Count; ++i) {
visited[i] = false;
indexOfName[codons[i].Id] = i;
}
}
void InsertEdges()
{
// add the InsertBefore to the corresponding InsertAfter
for (int i = 0; i < codons.Count; ++i) {
string before = codons[i].InsertBefore;
if (before != null && before != "") {
if (indexOfName.ContainsKey(before)) {
string after = codons[indexOfName[before]].InsertAfter;
if (after == null || after == "") {
codons[indexOfName[before]].InsertAfter = codons[i].Id;
} else {
codons[indexOfName[before]].InsertAfter = after + ',' + codons[i].Id;
}
} else {
LoggingService.WarnFormatted("Codon ({0}) specified in the insertbefore of the {1} codon does not exist!", before, codons[i]);
}
}
}
}
public List<Codon> Execute()
{
InsertEdges();
// Visit all codons
for (int i = 0; i < codons.Count; ++i) {
Visit(i);
}
return sortedCodons;
}
void Visit(int codonIndex)
{
if (visited[codonIndex]) {
return;
}
string[] after = codons[codonIndex].InsertAfter.Split(new char[] {','});
foreach (string s in after) {
if (s == null || s.Length == 0) {
continue;
}
if (indexOfName.ContainsKey(s)) {
Visit(indexOfName[s]);
} else {
LoggingService.WarnFormatted("Codon ({0}) specified in the insertafter of the {1} codon does not exist!", codons[codonIndex].InsertAfter, codons[codonIndex]);
}
}
sortedCodons.Add(codons[codonIndex]);
visited[codonIndex] = true;
}
}
/// <summary>
/// Builds the child items in this path. Ensures that all items have the type T.
/// </summary>
/// <param name="caller">The owner used to create the objects.</param>
public List<T> BuildChildItems<T>(object caller)
{
var codons = this.Codons;
List<T> items = new List<T>(codons.Count);
if (!isSorted) {
codons = (new TopologicalSort(codons)).Execute();
isSorted = true;
}
foreach (Codon codon in codons) {
ArrayList subItems = null;
if (childNodes.ContainsKey(codon.Id)) {
@ -171,11 +119,8 @@ namespace ICSharpCode.Core @@ -171,11 +119,8 @@ namespace ICSharpCode.Core
/// <param name="caller">The owner used to create the objects.</param>
public ArrayList BuildChildItems(object caller)
{
var codons = this.Codons;
ArrayList items = new ArrayList(codons.Count);
if (!isSorted) {
codons = (new TopologicalSort(codons)).Execute();
isSorted = true;
}
foreach (Codon codon in codons) {
ArrayList subItems = null;
if (childNodes.ContainsKey(codon.Id)) {
@ -207,7 +152,7 @@ namespace ICSharpCode.Core @@ -207,7 +152,7 @@ namespace ICSharpCode.Core
/// </exception>
public object BuildChildItem(string childItemID, object caller, ArrayList subItems)
{
foreach (Codon codon in codons) {
foreach (Codon codon in this.Codons) {
if (codon.Id == childItemID) {
return codon.BuildItem(caller, subItems);
}

87
src/Main/Core/Project/Src/AddInTree/TopologicalSort.cs

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Daniel Grunwald"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
namespace ICSharpCode.Core
{
/// <summary>
/// Supports sorting codons using InsertBefore/InsertAfter
/// </summary>
static class TopologicalSort
{
sealed class Node
{
internal Codon codon;
internal bool visited;
internal List<Node> previous = new List<Node>();
internal void Visit(List<Codon> output)
{
if (visited)
return;
visited = true;
foreach (Node n in previous)
n.Visit(output);
output.Add(codon);
}
}
public static List<Codon> Sort(IEnumerable<IEnumerable<Codon>> codonInput)
{
// Step 1: create nodes for graph
Dictionary<string, Node> nameToNodeDict = new Dictionary<string, Node>();
List<Node> allNodes = new List<Node>();
foreach (IEnumerable<Codon> codonList in codonInput) {
// create entries to preserve order within
Node previous = null;
foreach (Codon codon in codonList) {
Node node = new Node();
node.codon = codon;
if (!string.IsNullOrEmpty(codon.Id))
nameToNodeDict[codon.Id] = node;
// add implicit edges
if (previous != null)
node.previous.Add(previous);
allNodes.Add(node);
previous = node;
}
}
// Step 2: create edges from InsertBefore/InsertAfter values
foreach (Node node in allNodes) {
if (!string.IsNullOrEmpty(node.codon.InsertBefore)) {
foreach (string beforeReference in node.codon.InsertBefore.Split(',')) {
Node referencedNode;
if (nameToNodeDict.TryGetValue(beforeReference, out referencedNode)) {
referencedNode.previous.Add(node);
} else {
LoggingService.WarnFormatted("Codon ({0}) specified in the insertbefore of the {1} codon does not exist!", beforeReference, node.codon);
}
}
}
if (!string.IsNullOrEmpty(node.codon.InsertAfter)) {
foreach (string afterReference in node.codon.InsertAfter.Split(',')) {
Node referencedNode;
if (nameToNodeDict.TryGetValue(afterReference, out referencedNode)) {
node.previous.Add(referencedNode);
} else {
LoggingService.WarnFormatted("Codon ({0}) specified in the insertafter of the {1} codon does not exist!", afterReference, node.codon);
}
}
}
}
// Step 3: Perform Topological Sort
List<Codon> output = new List<Codon>();
foreach (Node node in allNodes) {
node.Visit(output);
}
return output;
}
}
}

6
src/Main/Core/Test/AssemblyInfo.cs

@ -31,9 +31,3 @@ using System.Runtime.CompilerServices; @@ -31,9 +31,3 @@ using System.Runtime.CompilerServices;
// numbers with the '*' character (the default):
[assembly: AssemblyVersion("2.0.0.1")]
// The following attributes specify the key for the sign of your assembly. See the
// .NET Framework documentation for more information about signing.
// This is not required, if you don't want signing let these attributes like they're.
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]

7
src/Main/Core/Test/ICSharpCode.Core.Tests.csproj

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@ -22,6 +23,10 @@ @@ -22,6 +23,10 @@
<PlatformTarget>AnyCPU</PlatformTarget>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\ICSharpCode.SharpDevelop.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>

39
src/Main/Core/Test/TopologicalSortTest.cs

@ -10,20 +10,43 @@ using System.Collections.Generic; @@ -10,20 +10,43 @@ using System.Collections.Generic;
using System.IO;
using NUnit.Framework;
namespace ICSharpCode.Core.Tests.AddInTreeTests.Tests
namespace ICSharpCode.Core.Tests
{
/*
[TestFixture]
public class TopologicalSortTest
{
[Test, Ignore("TODO: Write test")]
[Test]
public void Test()
{
List<Codon> codons = new List<Codon>();
for (int i = 0; i < 5; ++i) {
codons.Add(new Codon(null, "codon" + i, null, null));
}
var input = new List<List<Codon>> {
new List<Codon> {
CreateCodon("1"),
CreateCodon("2"),
CreateCodon("3")
},
new List<Codon> {
CreateCodon("4"),
CreateCodon("5"),
CreateCodon("6"),
},
new List<Codon> {
CreateCodon("7", insertAfter: "3"),
CreateCodon("8"),
CreateCodon("9", insertBefore: "4")
}
};
Assert.AreEqual(new string[] { "1", "2", "3", "7", "8", "9", "4", "5", "6" },
TopologicalSort.Sort(input).ConvertAll(c => c.Id).ToArray());
}
Codon CreateCodon(string id, string insertBefore = null, string insertAfter = null)
{
Properties p = new Properties();
p["id"] = id;
p["insertbefore"] = insertBefore;
p["insertafter"] = insertAfter;
return new Codon(null, id, p, null);
}
}
*/
}

3
src/Main/ICSharpCode.SharpDevelop.Dom/Project/Src/Refactoring/RefactoringProvider.cs

@ -95,6 +95,3 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring @@ -95,6 +95,3 @@ namespace ICSharpCode.SharpDevelop.Dom.Refactoring
#endregion
}
}

Loading…
Cancel
Save