Browse Source

Refactored parser service.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
ab95b18a3f
  1. 2
      SharpDevelop.sln
  2. 13
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs
  3. 8
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs
  4. 3
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs
  5. 6
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs
  6. 19
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs
  7. 2
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpMyNamespaceBuilder.cs
  8. 7
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs
  9. 3
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs
  10. 7
      src/AddIns/BackendBindings/CSharpBinding/Tests/MockTextEditor.cs
  11. 1
      src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.csproj
  12. 26
      src/AddIns/BackendBindings/CppBinding/CppBinding/Project/DependencyRelation.cs
  13. 160
      src/AddIns/BackendBindings/CppBinding/CppBinding/Project/MultiDictionary.cs
  14. 5
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlOutlineContentHost.xaml.cs
  15. 15
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs
  16. 5
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlSymbolSearch.cs
  17. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs
  18. 10
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs
  19. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs
  20. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs
  21. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs
  22. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs
  23. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs
  24. 4
      src/AddIns/VersionControl/GitAddIn/Src/OverlayIconManager.cs
  25. 4
      src/AddIns/VersionControl/SubversionAddIn/Src/Gui/ProjectBrowserVisitor/OverlayIconManager.cs
  26. 28
      src/Main/Base/Project/ICSharpCode.SharpDevelop.addin
  27. 13
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  28. 2
      src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs
  29. 3
      src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs
  30. 2
      src/Main/Base/Project/Src/Editor/ToolTipRequestEventArgs.cs
  31. 6
      src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs
  32. 3
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs
  33. 5
      src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/TaskListOptionsl.xaml.cs
  34. 2
      src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/GacReferencePanel.cs
  35. 4
      src/Main/Base/Project/Src/Gui/Dialogs/WordCountDialog.cs
  36. 5
      src/Main/Base/Project/Src/Gui/IWorkbench.cs
  37. 7
      src/Main/Base/Project/Src/Gui/Pads/DefinitionViewPad.cs
  38. 4
      src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs
  39. 2
      src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs
  40. 6
      src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs
  41. 5
      src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPadCommands.cs
  42. 72
      src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs
  43. 2
      src/Main/Base/Project/Src/Internal/Templates/Project/ProjectDescriptor.cs
  44. 11
      src/Main/Base/Project/Src/Project/AbstractProject.cs
  45. 13
      src/Main/Base/Project/Src/Project/CompilableProject.cs
  46. 2
      src/Main/Base/Project/Src/Project/CustomTool.cs
  47. 12
      src/Main/Base/Project/Src/Project/IProject.cs
  48. 3
      src/Main/Base/Project/Src/Project/ProjectChangeWatcher.cs
  49. 10
      src/Main/Base/Project/Src/Refactoring/EditorRefactoringContext.cs
  50. 3
      src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs
  51. 6
      src/Main/Base/Project/Src/Services/File/FileService.cs
  52. 55
      src/Main/Base/Project/Src/Services/File/IFileService.cs
  53. 4
      src/Main/Base/Project/Src/Services/File/OpenedFile.cs
  54. 93
      src/Main/Base/Project/Src/Services/IMessageLoop.cs
  55. 2
      src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs
  56. 11
      src/Main/Base/Project/Src/Services/ParserService/DomAssemblyName.cs
  57. 30
      src/Main/Base/Project/Src/Services/ParserService/IGlobalAssemblyCacheService.cs
  58. 23
      src/Main/Base/Project/Src/Services/ParserService/IParser.cs
  59. 291
      src/Main/Base/Project/Src/Services/ParserService/IParserService.cs
  60. 13
      src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs
  61. 42
      src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs
  62. 18
      src/Main/Base/Project/Src/Services/ParserService/ParsedFileListener.cs
  63. 1026
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  64. 6
      src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentFinder.cs
  65. 4
      src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs
  66. 35
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs
  67. 19
      src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs
  68. 18
      src/Main/Base/Project/Src/Services/SD.cs
  69. 6
      src/Main/Base/Project/Src/Services/Tasks/TaskService.cs
  70. 2
      src/Main/Base/Project/Src/Util/ExtensionMethods.cs
  71. 115
      src/Main/Base/Project/Src/Util/MultiDictionary.cs
  72. 16
      src/Main/Base/Project/Src/Util/ReactiveExtensions.cs
  73. 112
      src/Main/Base/Project/Src/Util/WorkerThread.cs
  74. 120
      src/Main/Base/Project/Src/Util/WpfSynchronizeInvoke.cs
  75. 0
      src/Main/SharpDevelop/Parser/Fusion.cs
  76. 28
      src/Main/SharpDevelop/Parser/GlobalAssemblyCacheService.cs
  77. 2
      src/Main/SharpDevelop/Parser/ParserDescriptor.cs
  78. 2
      src/Main/SharpDevelop/Parser/ParserDoozer.cs
  79. 359
      src/Main/SharpDevelop/Parser/ParserService.cs
  80. 330
      src/Main/SharpDevelop/Parser/ParserServiceEntry.cs
  81. 2
      src/Main/SharpDevelop/Sda/CallHelper.cs
  82. 45
      src/Main/SharpDevelop/SharpDevelop.csproj
  83. 2
      src/Main/SharpDevelop/Startup/App.xaml
  84. 2
      src/Main/SharpDevelop/Startup/App.xaml.cs
  85. 4
      src/Main/SharpDevelop/Startup/SharpDevelopMain.cs
  86. 2
      src/Main/SharpDevelop/Startup/SplashScreen.cs
  87. 3
      src/Main/SharpDevelop/Workbench/AvalonDockLayout.cs
  88. 3
      src/Main/SharpDevelop/Workbench/AvalonPadContent.cs
  89. 3
      src/Main/SharpDevelop/Workbench/AvalonWorkbenchWindow.cs
  90. 7
      src/Main/SharpDevelop/Workbench/ChooseLayoutCommand.cs
  91. 146
      src/Main/SharpDevelop/Workbench/DispatcherMessageLoop.cs
  92. 61
      src/Main/SharpDevelop/Workbench/FileService.cs
  93. 2
      src/Main/SharpDevelop/Workbench/FullScreenEnabledWindow.cs
  94. 9
      src/Main/SharpDevelop/Workbench/LayoutConfiguration.cs
  95. 3
      src/Main/SharpDevelop/Workbench/SDStatusBar.cs
  96. 15
      src/Main/SharpDevelop/Workbench/SingleInstanceHelper.cs
  97. 5
      src/Main/SharpDevelop/Workbench/StatusBarService.cs
  98. 20
      src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs
  99. 29
      src/Main/SharpDevelop/Workbench/WpfWorkbench.cs
  100. 8
      src/Main/SharpDevelop/Workbench/WpfWorkbench.xaml

2
SharpDevelop.sln

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
# SharpDevelop 4.2.0.8695-Beta 2
# SharpDevelop 4.2.0.8707-Beta 2
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main", "Main", "{256F5C28-532C-44C0-8AB8-D8EC5E492E01}"
ProjectSection(SolutionItems) = postProject
EndProjectSection

13
src/AddIns/BackendBindings/CSharpBinding/Project/Src/CSharpSemanticHighlighter.cs

@ -14,6 +14,7 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem; @@ -14,6 +14,7 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
@ -60,15 +61,15 @@ namespace CSharpBinding @@ -60,15 +61,15 @@ namespace CSharpBinding
this.valueKeywordColor = highlightingDefinition.GetNamedColor("NullOrValueKeywords");
this.parameterModifierColor = highlightingDefinition.GetNamedColor("ParameterModifiers");
ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated;
ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded;
SD.ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated;
SD.ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded;
syntaxHighlighter.VisibleDocumentLinesChanged += syntaxHighlighter_VisibleDocumentLinesChanged;
}
public void Dispose()
{
ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated;
ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded;
SD.ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated;
SD.ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded;
syntaxHighlighter.VisibleDocumentLinesChanged -= syntaxHighlighter_VisibleDocumentLinesChanged;
}
#endregion
@ -202,7 +203,7 @@ namespace CSharpBinding @@ -202,7 +203,7 @@ namespace CSharpBinding
return cachedLine.HighlightedLine;
}
var parseInfo = ParserService.GetCachedParseInformation(textEditor.FileName, textEditor.Document.Version) as CSharpFullParseInformation;
var parseInfo = SD.ParserService.GetCachedParseInformation(textEditor.FileName, textEditor.Document.Version) as CSharpFullParseInformation;
if (parseInfo == null) {
if (!invalidLines.Contains(documentLine))
invalidLines.Add(documentLine);
@ -218,7 +219,7 @@ namespace CSharpBinding @@ -218,7 +219,7 @@ namespace CSharpBinding
}
}
var compilation = ParserService.GetCompilationForFile(parseInfo.FileName);
var compilation = SD.ParserService.GetCompilationForFile(parseInfo.FileName);
this.resolver = parseInfo.GetResolver(compilation);
HighlightedLine line = new HighlightedLine(textEditor.Document, documentLine);

8
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/CSharpCompletionBinding.cs

@ -4,11 +4,11 @@ @@ -4,11 +4,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using CSharpBinding.Parser;
using ICSharpCode.NRefactory.Completion;
using ICSharpCode.NRefactory.CSharp.Completion;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
using ICSharpCode.SharpDevelop.Parser;
@ -38,13 +38,13 @@ namespace CSharpBinding.Completion @@ -38,13 +38,13 @@ namespace CSharpBinding.Completion
bool ShowCompletion(ITextEditor editor, char completionChar, bool ctrlSpace)
{
// Don't require the very latest parse information, an older cached version is OK.
var parseInfo = ParserService.GetCachedParseInformation(editor.FileName) as CSharpFullParseInformation;
var parseInfo = SD.ParserService.GetCachedParseInformation(editor.FileName) as CSharpFullParseInformation;
if (parseInfo == null) {
parseInfo = ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
parseInfo = SD.ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
if (parseInfo == null)
return false;
}
ICompilation compilation = ParserService.GetCompilationForFile(editor.FileName);
ICompilation compilation = SD.ParserService.GetCompilationForFile(editor.FileName);
var pc = compilation.MainAssembly.UnresolvedAssembly as IProjectContent;
if (pc == null)
return false;

3
src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingStrategy.cs

@ -9,6 +9,7 @@ using ICSharpCode.AvalonEdit.Indentation.CSharp; @@ -9,6 +9,7 @@ using ICSharpCode.AvalonEdit.Indentation.CSharp;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
@ -180,7 +181,7 @@ namespace CSharpBinding.FormattingStrategy @@ -180,7 +181,7 @@ namespace CSharpBinding.FormattingStrategy
FileName fileName = editor.FileName;
IUnresolvedEntity nextElement = null;
if (fileName != null) {
IParsedFile parsedFile = ParserService.ParseFile(fileName, editor.Document.CreateSnapshot());
IParsedFile parsedFile = SD.ParserService.ParseFile(fileName, editor.Document);
if (parsedFile != null) {
var currentClass = parsedFile.GetInnermostTypeDefinition(caretLine, 0);
int nextElementLine = int.MaxValue;

6
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpSymbolSearch.cs

@ -8,7 +8,6 @@ using System.Linq; @@ -8,7 +8,6 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using CSharpBinding.Parser;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core;
@ -19,6 +18,7 @@ using ICSharpCode.NRefactory.Editor; @@ -19,6 +18,7 @@ using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.Utils;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
@ -44,7 +44,7 @@ namespace CSharpBinding @@ -44,7 +44,7 @@ namespace CSharpBinding
{
this.project = project;
searchScopes = fr.GetSearchScopes(entity);
compilation = ParserService.GetCompilation(project);
compilation = SD.ParserService.GetCompilation(project);
interestingFileNames = new IList<string>[searchScopes.Count];
for (int i = 0; i < searchScopes.Count; i++) {
interestingFileNames[i] = fr.GetInterestingFiles(searchScopes[i], compilation).Select(f => f.FileName).ToList();
@ -93,7 +93,7 @@ namespace CSharpBinding @@ -93,7 +93,7 @@ namespace CSharpBinding
return;
}
var parseInfo = ParserService.Parse(fileName, textSource) as CSharpFullParseInformation;
var parseInfo = SD.ParserService.Parse(fileName, textSource) as CSharpFullParseInformation;
if (parseInfo == null)
return;
ReadOnlyDocument document = null;

19
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs

@ -28,17 +28,7 @@ namespace CSharpBinding.Parser @@ -28,17 +28,7 @@ namespace CSharpBinding.Parser
{
public class TParser : IParser
{
///<summary>IParser Interface</summary>
string[] lexerTags;
public string[] LexerTags {
get {
return lexerTags;
}
set {
lexerTags = value;
}
}
public IReadOnlyList<string> TaskListTokens { get; set; }
public bool CanParse(string fileName)
{
@ -77,7 +67,8 @@ namespace CSharpBinding.Parser @@ -77,7 +67,8 @@ namespace CSharpBinding.Parser
}
*/
public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested)
public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested,
IProject parentProject, CancellationToken cancellationToken)
{
CSharpParser parser = new CSharpParser();
parser.GenerateTypeSystemMode = !fullParseInformationRequested;
@ -102,7 +93,7 @@ namespace CSharpBinding.Parser @@ -102,7 +93,7 @@ namespace CSharpBinding.Parser
ReadOnlyDocument document = null;
foreach (var comment in cu.Descendants.OfType<Comment>().Where(c => c.CommentType != CommentType.InactiveCode)) {
int matchLength;
int index = comment.Content.IndexOfAny(lexerTags, 0, out matchLength);
int index = comment.Content.IndexOfAny(TaskListTokens, 0, out matchLength);
if (index > -1) {
if (document == null)
document = new ReadOnlyDocument(fileContent);
@ -115,7 +106,7 @@ namespace CSharpBinding.Parser @@ -115,7 +106,7 @@ namespace CSharpBinding.Parser
int endOffset = Math.Min(document.GetLineByNumber(startLocation.Line).EndOffset, document.GetOffset(comment.EndLocation) - commentEndSignLength);
string content = document.GetText(absoluteOffset, endOffset - absoluteOffset);
tagComments.Add(new TagComment(content.Substring(0, matchLength), new DomRegion(cu.FileName, startLocation.Line, startLocation.Column), content.Substring(matchLength)));
index = comment.Content.IndexOfAny(lexerTags, endOffset - startOffset - commentSignLength, out matchLength);
index = comment.Content.IndexOfAny(TaskListTokens, endOffset - startOffset - commentSignLength, out matchLength);
} while (index > -1);
}
}

2
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Project/CSharpMyNamespaceBuilder.cs

@ -63,7 +63,7 @@ namespace CSharpBinding @@ -63,7 +63,7 @@ namespace CSharpBinding
continue;
}
if (trimmedLine == "/*LIST OF FORMS*/") {
var compilation = ParserService.GetCompilation(vbProject);
var compilation = SD.ParserService.GetCompilation(vbProject);
ITypeDefinition myFormsClass = FindMyFormsClass(compilation.MainAssembly, ns);
if (myFormsClass != null) {
string indentation = line.Substring(0, line.Length - trimmedLine.Length);

7
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs

@ -15,6 +15,7 @@ using ICSharpCode.NRefactory; @@ -15,6 +15,7 @@ using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
@ -90,14 +91,14 @@ namespace CSharpBinding.Refactoring @@ -90,14 +91,14 @@ namespace CSharpBinding.Refactoring
{
this.editor = editor;
this.markerService = editor.GetService(typeof(ITextMarkerService)) as ITextMarkerService;
ParserService.ParserUpdateStepFinished += ParserService_ParserUpdateStepFinished;
//SD.ParserService.ParserUpdateStepFinished += ParserService_ParserUpdateStepFinished;
editor.ContextActionProviders.Add(this);
}
public void Dispose()
{
editor.ContextActionProviders.Remove(this);
ParserService.ParserUpdateStepFinished -= ParserService_ParserUpdateStepFinished;
//SD.ParserService.ParserUpdateStepFinished -= ParserService_ParserUpdateStepFinished;
if (cancellationTokenSource != null)
cancellationTokenSource.Cancel();
Clear();
@ -243,7 +244,7 @@ namespace CSharpBinding.Refactoring @@ -243,7 +244,7 @@ namespace CSharpBinding.Refactoring
try {
await Task.Run(
delegate {
var compilation = ParserService.GetCompilationForFile(parseInfo.FileName);
var compilation = SD.ParserService.GetCompilationForFile(parseInfo.FileName);
var resolver = parseInfo.GetResolver(compilation);
var context = new SDRefactoringContext(textSource, resolver, new TextLocation(0, 0), 0, 0, cancellationToken);
foreach (var issueProvider in issueProviders.Value) {

3
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs

@ -10,6 +10,7 @@ using ICSharpCode.NRefactory.CSharp; @@ -10,6 +10,7 @@ using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
@ -41,7 +42,7 @@ namespace CSharpBinding.Refactoring @@ -41,7 +42,7 @@ namespace CSharpBinding.Refactoring
public override void FormatText(AstNode node)
{
var parseInfo = ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
var parseInfo = SD.ParserService.Parse(editor.FileName, editor.Document) as CSharpFullParseInformation;
if (parseInfo != null) {
//var startLocation = editor.Document.GetLocation(offset);
//var endLocation = editor.Document.GetLocation(offset + length);

7
src/AddIns/BackendBindings/CSharpBinding/Tests/MockTextEditor.cs

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System.Threading;
using ICSharpCode.AvalonEdit.Highlighting;
using System;
using System.Collections.Generic;
@ -27,18 +28,16 @@ namespace CSharpBinding.Tests @@ -27,18 +28,16 @@ namespace CSharpBinding.Tests
public MockTextEditor()
: base(new TextEditor())
{
PropertyService.InitializeServiceForUnitTests();
}
public override FileName FileName {
get { return new FileName("mockFileName.cs"); }
}
public void CreateParseInformation()
public ParseInformation CreateParseInformation()
{
var parser = new CSharpBinding.Parser.TParser();
var parseInfo = parser.Parse(this.FileName, this.Document, true);
ParserService.RegisterParseInformation(parseInfo.FileName, parseInfo, parser);
return parser.Parse(this.FileName, this.Document, true, null, CancellationToken.None);
}
ICompletionItemList lastCompletionItemList;

1
src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.csproj

@ -71,7 +71,6 @@ @@ -71,7 +71,6 @@
<Compile Include="CppFormattingStrategy.cs" />
<Compile Include="CppLanguageBinding.cs" />
<Compile Include="Project\DependencyRelation.cs" />
<Compile Include="Project\MultiDictionary.cs" />
<Compile Include="Project\ApplicationOptions.cs">
<SubType>UserControl</SubType>
</Compile>

26
src/AddIns/BackendBindings/CppBinding/CppBinding/Project/DependencyRelation.cs

@ -3,9 +3,11 @@ @@ -3,9 +3,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Diagnostics;
using ICSharpCode.SharpDevelop;
namespace ICSharpCode.CppBinding.Project
{
@ -18,13 +20,14 @@ namespace ICSharpCode.CppBinding.Project @@ -18,13 +20,14 @@ namespace ICSharpCode.CppBinding.Project
: this(new MultiDictionary<T1, T2>())
{ }
public DependencyRelation(IMultiDictionary<T1, T2> innerDep)
public DependencyRelation(MultiDictionary<T1, T2> innerDep)
{
dep = innerDep;
revDep = new MultiDictionary<T2, T1>();
foreach (KeyValuePair<T1, T2> item in dep)
revDep.Add(item.Value, item.Key);
foreach (var group in dep)
foreach (var value in group)
revDep.Add(value, group.Key);
}
/// <summary>
@ -53,11 +56,9 @@ namespace ICSharpCode.CppBinding.Project @@ -53,11 +56,9 @@ namespace ICSharpCode.CppBinding.Project
/// Returns a list of items given element directly depend on.
/// If there is no element in the dependency relation, returns an empty list.
/// </summary>
public IList<T2> DependOn(T1 element)
public IReadOnlyList<T2> DependOn(T1 element)
{
if (dep.ContainsKey(element))
return dep[element];
return new List<T2>();
}
/// <summary>
@ -83,11 +84,9 @@ namespace ICSharpCode.CppBinding.Project @@ -83,11 +84,9 @@ namespace ICSharpCode.CppBinding.Project
/// If the is no item that depend on given element, returns an empty list.
/// </summary>
/// <returns></returns>
public IList<T1> DependingOn(T2 element)
public IReadOnlyList<T1> DependingOn(T2 element)
{
if (revDep.ContainsKey(element))
return revDep[element];
return new List<T1>();
}
/// <summary>
@ -108,7 +107,7 @@ namespace ICSharpCode.CppBinding.Project @@ -108,7 +107,7 @@ namespace ICSharpCode.CppBinding.Project
return DependencyTree(revDep, element).Cast<T1>();
}
IEnumerable<T> DependencyTree<T, U>(IMultiDictionary<T, U> rel, T startItem)
IEnumerable<T> DependencyTree<T, U>(MultiDictionary<T, U> rel, T startItem)
{
HashSet<T> visited = new HashSet<T>();
Stack<T> pendingItems = new Stack<T>();
@ -117,7 +116,6 @@ namespace ICSharpCode.CppBinding.Project @@ -117,7 +116,6 @@ namespace ICSharpCode.CppBinding.Project
while (pendingItems.Count > 0)
{
T currentItem = pendingItems.Pop();
if (rel.ContainsKey(currentItem))
foreach (T depend in rel[currentItem].Cast<T>())
if (!visited.Contains(depend))
{
@ -129,9 +127,9 @@ namespace ICSharpCode.CppBinding.Project @@ -129,9 +127,9 @@ namespace ICSharpCode.CppBinding.Project
}
//dependency relation
IMultiDictionary<T1, T2> dep;
MultiDictionary<T1, T2> dep;
//reverse dependency relation
IMultiDictionary<T2, T1> revDep;
MultiDictionary<T2, T1> revDep;
}
}

160
src/AddIns/BackendBindings/CppBinding/CppBinding/Project/MultiDictionary.cs

@ -1,160 +0,0 @@ @@ -1,160 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
namespace ICSharpCode.CppBinding.Project
{
public interface IMultiDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>
{
void Add(TKey key, TValue value);
bool Contains(TKey key, TValue value);
bool ContainsKey(TKey key);
bool Remove(TKey key, TValue value);
IList<TValue> this[TKey key] { get; }
}
/// <summary>
/// A dictionary that allows multiple pairs with the same key.
/// </summary>
public class MultiDictionary<TKey, TValue> : IMultiDictionary<TKey,TValue>
{
public MultiDictionary()
: this(new Dictionary<TKey, IList<TValue>>())
{ }
public MultiDictionary(IDictionary<TKey, IList<TValue>> innerDictionary)
{
if (innerDictionary == null)
throw new ArgumentNullException("innerDictionary");
dict = innerDictionary;
count = CountElements(dict);
}
IDictionary<TKey, IList<TValue>> dict;
int count;
public void Add(TKey key, TValue value)
{
IList<TValue> valueList;
if (!dict.TryGetValue(key, out valueList))
{
valueList = new List<TValue>();
dict.Add(key, valueList);
}
valueList.Add(value);
count++;
}
public bool Contains(TKey key, TValue value)
{
IList<TValue> valueList;
if (!dict.TryGetValue(key, out valueList))
return false;
return valueList.Contains(value);
}
public bool ContainsKey(TKey key)
{
return dict.ContainsKey(key);
}
public bool Remove(TKey key, TValue value)
{
IList<TValue> valueList;
if (!dict.TryGetValue(key, out valueList))
return false;
return valueList.Remove(value);
}
public IList<TValue> this[TKey key]
{
get
{
return new ReadOnlyCollection<TValue>(dict[key]);
}
}
#region ICollection<KeyValuePair<TKey,TValue>> Members
public void Add(KeyValuePair<TKey, TValue> item)
{
Add(item.Key, item.Value);
}
public void Clear()
{
dict.Clear();
count = 0;
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
return Contains(item.Key, item.Value);
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException("array");
if (arrayIndex < 0)
throw new ArgumentOutOfRangeException("arrayIndex");
if (array.Rank != 1)
throw new ArgumentException("Array is multidimensional", "array");
if (arrayIndex + count >= array.Length)
throw new ArgumentException("Array is to small", "array");
foreach (KeyValuePair<TKey, IList<TValue>> item in dict)
foreach (TValue value in item.Value)
array[arrayIndex++] = new KeyValuePair<TKey, TValue>(item.Key, value);
}
public int Count
{
get { return count; }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
return Remove(item.Key, item.Value);
}
#endregion
#region IEnumerable<KeyValuePair<TKey,TValue>> Members
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (KeyValuePair<TKey, IList<TValue>> item in dict)
foreach (TValue value in item.Value)
yield return new KeyValuePair<TKey, TValue>(item.Key, value);
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
static int CountElements(IDictionary<TKey, IList<TValue>> dict)
{
int count = 0;
foreach (KeyValuePair<TKey, IList<TValue>> item in dict)
count += item.Value.Count;
return count;
}
}
}

5
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlOutlineContentHost.xaml.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.XamlBinding @@ -27,7 +27,7 @@ namespace ICSharpCode.XamlBinding
InitializeComponent();
ParserService.ParseInformationUpdated += ParseInfoUpdated;
SD.ParserService.ParseInformationUpdated += ParseInfoUpdated;
}
void ParseInfoUpdated(object sender, ParseInformationEventArgs e)
@ -35,6 +35,7 @@ namespace ICSharpCode.XamlBinding @@ -35,6 +35,7 @@ namespace ICSharpCode.XamlBinding
if (this.editor == null || !FileUtility.IsEqualFileName(this.editor.FileName, e.FileName))
return;
#warning Reimplement XAML outline
// var cu = e.NewCompilationUnit as XamlCompilationUnit;
//
// if (cu != null && cu.TreeRootNode != null)
@ -103,7 +104,7 @@ namespace ICSharpCode.XamlBinding @@ -103,7 +104,7 @@ namespace ICSharpCode.XamlBinding
public void Dispose()
{
ParserService.ParseInformationUpdated -= ParseInfoUpdated;
SD.ParserService.ParseInformationUpdated -= ParseInfoUpdated;
}
}
}

15
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs

@ -27,13 +27,7 @@ namespace ICSharpCode.XamlBinding @@ -27,13 +27,7 @@ namespace ICSharpCode.XamlBinding
/// </summary>
public class XamlParser : IParser
{
string[] lexerTags;
public string[] LexerTags
{
get { return lexerTags; }
set { lexerTags = value; }
}
public IReadOnlyList<string> TaskListTokens { get; set; }
// public LanguageProperties Language
// {
@ -132,7 +126,8 @@ namespace ICSharpCode.XamlBinding @@ -132,7 +126,8 @@ namespace ICSharpCode.XamlBinding
volatile IncrementalParserState parserState;
public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested)
public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested,
IProject parentProject, CancellationToken cancellationToken)
{
AXmlParser parser = new AXmlParser();
AXmlDocument document;
@ -155,7 +150,7 @@ namespace ICSharpCode.XamlBinding @@ -155,7 +150,7 @@ namespace ICSharpCode.XamlBinding
foreach (var tag in TreeTraversal.PreOrder<AXmlObject>(xmlDocument, node => node.Children).OfType<AXmlTag>().Where(t => t.IsComment)) {
int matchLength;
AXmlText comment = tag.Children.OfType<AXmlText>().First();
int index = comment.Value.IndexOfAny(lexerTags, 0, out matchLength);
int index = comment.Value.IndexOfAny(TaskListTokens, 0, out matchLength);
if (index > -1) {
if (document == null)
document = fileContent as IDocument ?? new ReadOnlyDocument(fileContent);
@ -165,7 +160,7 @@ namespace ICSharpCode.XamlBinding @@ -165,7 +160,7 @@ namespace ICSharpCode.XamlBinding
int endOffset = Math.Min(document.GetLineByOffset(startOffset).EndOffset, comment.EndOffset);
string content = document.GetText(startOffset, endOffset - startOffset);
parseInfo.TagComments.Add(new TagComment(content.Substring(0, matchLength), new DomRegion(parseInfo.FileName, startLocation.Line, startLocation.Column), content.Substring(matchLength)));
index = comment.Value.IndexOfAny(lexerTags, endOffset - comment.StartOffset, out matchLength);
index = comment.Value.IndexOfAny(TaskListTokens, endOffset - comment.StartOffset, out matchLength);
} while (index > -1);
}
}

5
src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlSymbolSearch.cs

@ -13,6 +13,7 @@ using ICSharpCode.NRefactory.CSharp.Resolver; @@ -13,6 +13,7 @@ using ICSharpCode.NRefactory.CSharp.Resolver;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor.Search;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project;
@ -35,7 +36,7 @@ namespace ICSharpCode.XamlBinding @@ -35,7 +36,7 @@ namespace ICSharpCode.XamlBinding
public XamlSymbolSearch(IProject project, IEntity entity)
{
this.entity = entity;
compilation = ParserService.GetCompilation(project);
compilation = SD.ParserService.GetCompilation(project);
interestingFileNames = new List<FileName>();
foreach (var item in project.ParentSolution.SolutionFolderContainers.Select(f => f.SolutionItems).SelectMany(si => si.Items).Where(i => ".xaml".Equals(Path.GetExtension(i.Location), StringComparison.OrdinalIgnoreCase)))
interestingFileNames.Add(new FileName(Path.Combine(project.ParentSolution.Directory, item.Location)));
@ -81,7 +82,7 @@ namespace ICSharpCode.XamlBinding @@ -81,7 +82,7 @@ namespace ICSharpCode.XamlBinding
if (offset < 0)
return;
var parseInfo = ParserService.Parse(fileName, textSource) as XamlFullParseInformation;
var parseInfo = SD.ParserService.Parse(fileName, textSource) as XamlFullParseInformation;
if (parseInfo == null)
return;
ReadOnlyDocument document = null;

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/AvalonEditViewContent.cs

@ -171,7 +171,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -171,7 +171,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
FileName newFileName = file.FileName;
if (!string.IsNullOrEmpty(oldFileName))
ParserService.ClearParseInformation(oldFileName);
SD.ParserService.ClearParseInformation(oldFileName);
BookmarksNotifyNameChange(oldFileName, newFileName);
@ -182,7 +182,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -182,7 +182,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
codeEditor.FileName = newFileName;
UpdateSyntaxHighlighting(newFileName);
ParserService.ParseAsync(file.FileName, codeEditor.Document).FireAndForget();
SD.ParserService.ParseAsync(file.FileName, codeEditor.Document).FireAndForget();
}
}

10
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditor.cs

@ -141,7 +141,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -141,7 +141,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
{
CodeEditorOptions.Instance.PropertyChanged += CodeEditorOptions_Instance_PropertyChanged;
CustomizedHighlightingColor.ActiveColorsChanged += CustomizedHighlightingColor_ActiveColorsChanged;
ParserService.ParseInformationUpdated += ParserServiceParseInformationUpdated;
SD.ParserService.ParseInformationUpdated += ParserServiceParseInformationUpdated;
this.FlowDirection = FlowDirection.LeftToRight; // code editing is always left-to-right
this.CommandBindings.Add(new CommandBinding(SharpDevelopRoutedCommands.SplitView, OnSplitView));
@ -476,7 +476,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -476,7 +476,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
// Immediately parse on enter.
// This ensures we have up-to-date CC info about the method boundary when a user
// types near the end of a method.
ParserService.ParseAsync(this.FileName, this.Document.CreateSnapshot()).FireAndForget();
SD.ParserService.ParseAsync(this.FileName, this.Document.CreateSnapshot()).FireAndForget();
} else {
if (e.Text.Length == 1) {
foreach (ICodeCompletionBinding cc in CodeCompletionBindings) {
@ -539,10 +539,10 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -539,10 +539,10 @@ namespace ICSharpCode.AvalonEdit.AddIn
void FetchParseInformation()
{
ParseInformation parseInfo = ParserService.GetCachedParseInformation(this.FileName);
ParseInformation parseInfo = SD.ParserService.GetCachedParseInformation(this.FileName);
if (parseInfo == null) {
// if parse info is not yet available, start parsing on background
ParserService.ParseAsync(this.FileName, primaryTextEditorAdapter.Document).FireAndForget();
SD.ParserService.ParseAsync(this.FileName, primaryTextEditorAdapter.Document).FireAndForget();
// we'll receive the result using the ParseInformationUpdated event
}
ParseInformationUpdated(parseInfo);
@ -600,7 +600,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -600,7 +600,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
{
CodeEditorOptions.Instance.PropertyChanged -= CodeEditorOptions_Instance_PropertyChanged;
CustomizedHighlightingColor.ActiveColorsChanged -= CustomizedHighlightingColor_ActiveColorsChanged;
ParserService.ParseInformationUpdated -= ParserServiceParseInformationUpdated;
SD.ParserService.ParseInformationUpdated -= ParserServiceParseInformationUpdated;
if (primaryTextEditorAdapter.Language != null)
primaryTextEditorAdapter.Language.Detach();

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs

@ -550,7 +550,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -550,7 +550,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
parseInfo = null;
} else {
if (parseInfo == null || !parseInfo.IsFullParseInformation)
parseInfo = ParserService.Parse(this.FileName, this.Document);
parseInfo = SD.ParserService.Parse(this.FileName, this.Document);
}
IServiceContainer container = this.Adapter.GetService(typeof(IServiceContainer)) as IServiceContainer;

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs

@ -6,9 +6,9 @@ using System.Collections.Generic; @@ -6,9 +6,9 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Refactoring;
@ -83,7 +83,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.ContextActions @@ -83,7 +83,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.ContextActions
/// </summary>
async Task<IEnumerable<IContextAction>> GetActionsAsync(IEnumerable<IContextActionProvider> providers, CancellationToken cancellationToken)
{
if (ParserService.LoadSolutionProjectsThreadRunning)
if (SD.ParserService.LoadSolutionProjectsThreadRunning)
return EmptyList<IContextAction>.Instance;
var providerList = providers.ToList();
var actions = await Task.WhenAll(providerList.Select(p => p.GetAvailableActionsAsync(this.EditorContext, cancellationToken)));

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/DefaultChangeWatcher.cs

@ -4,11 +4,11 @@ @@ -4,11 +4,11 @@
using System;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Widgets.MyersDiff;
@ -137,7 +137,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -137,7 +137,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
stream.CopyTo(memory);
stream.Close();
memory.Position = 0;
return FileReader.ReadFileContent(memory, ParserService.DefaultFileEncoding);
return FileReader.ReadFileContent(memory, SD.FileService.DefaultFileEncoding);
}
Stream GetBaseVersion(FileName fileName)

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs

@ -242,7 +242,7 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -242,7 +242,7 @@ namespace ICSharpCode.AvalonEdit.AddIn
IUnresolvedTypeDefinition selectedClass = item != null ? item.Entity as IUnresolvedTypeDefinition : null;
memberItems = new List<EntityItem>();
if (selectedClass != null) {
ICompilation compilation = ParserService.GetCompilationForFile(FileName.Create(selectedClass.ParsedFile.FileName));
ICompilation compilation = SD.ParserService.GetCompilationForFile(FileName.Create(selectedClass.ParsedFile.FileName));
var context = new SimpleTypeResolveContext(compilation.MainAssembly);
ITypeDefinition compoundClass = selectedClass.Resolve(context).GetDefinition();
if (compoundClass != null) {

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/CodeSnippet.cs

@ -194,7 +194,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets @@ -194,7 +194,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.Snippets
static IUnresolvedTypeDefinition GetCurrentClass(ITextEditor editor)
{
var parseInfo = ParserService.GetExistingParsedFile(editor.FileName);
var parseInfo = SD.ParserService.GetExistingParsedFile(editor.FileName);
if (parseInfo != null) {
return parseInfo.GetInnermostTypeDefinition(editor.Caret.Location);
}

4
src/AddIns/VersionControl/GitAddIn/Src/OverlayIconManager.cs

@ -7,9 +7,9 @@ using System.Diagnostics; @@ -7,9 +7,9 @@ using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
@ -83,7 +83,7 @@ namespace ICSharpCode.GitAddIn @@ -83,7 +83,7 @@ namespace ICSharpCode.GitAddIn
// sleep a tiny bit to give main thread time to add more jobs to the queue
Thread.Sleep(100);
while (true) {
if (ICSharpCode.SharpDevelop.Parser.ParserService.LoadSolutionProjectsThreadRunning) {
if (SD.ParserService.LoadSolutionProjectsThreadRunning) {
// Run OverlayIconManager much more slowly while solution is being loaded.
// This prevents the disk from seeking too much
Thread.Sleep(100);

4
src/AddIns/VersionControl/SubversionAddIn/Src/Gui/ProjectBrowserVisitor/OverlayIconManager.cs

@ -6,9 +6,9 @@ using System.Collections.Generic; @@ -6,9 +6,9 @@ using System.Collections.Generic;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.Svn
@ -139,7 +139,7 @@ namespace ICSharpCode.Svn @@ -139,7 +139,7 @@ namespace ICSharpCode.Svn
// sleep a tiny bit to give main thread time to add more jobs to the queue
Thread.Sleep(2);
while (true) {
if (ICSharpCode.SharpDevelop.Parser.ParserService.LoadSolutionProjectsThreadRunning) {
if (SD.ParserService.LoadSolutionProjectsThreadRunning) {
// Run OverlayIconManager much more slowly while solution is being loaded.
// This prevents the disk from seeking too much
Thread.Sleep(100);

28
src/Main/Base/Project/ICSharpCode.SharpDevelop.addin

@ -41,7 +41,6 @@ @@ -41,7 +41,6 @@
<Doozer name="Pad" class="ICSharpCode.SharpDevelop.PadDoozer"/>
<Doozer name="ProjectBinding" class="ICSharpCode.SharpDevelop.ProjectBindingDoozer"/>
<Doozer name="LanguageBinding" class="ICSharpCode.SharpDevelop.LanguageBindingDoozer"/>
<Doozer name="Parser" class="ICSharpCode.SharpDevelop.Parser.ParserDoozer"/>
<Doozer name="BrowserSchemeExtension" class="ICSharpCode.SharpDevelop.BrowserDisplayBinding.SchemeExtensionDoozer"/>
<Doozer name="CodeCompletionBinding" class="ICSharpCode.SharpDevelop.Editor.CodeCompletion.CodeCompletionBindingDoozer"/>
<Doozer name="Debugger" class="ICSharpCode.SharpDevelop.Debugging.DebuggerDoozer"/>
@ -49,9 +48,20 @@ @@ -49,9 +48,20 @@
<Doozer name="TaskBoundAdditionalLogger" class="ICSharpCode.SharpDevelop.Project.TaskBoundAdditionalLoggerDoozer"/>
<Doozer name="TaskBoundLoggerFilter" class="ICSharpCode.SharpDevelop.Project.TaskBoundLoggerFilterDoozer"/>
</Import>
<Import assembly=":SharpDevelop"/>
<Import assembly=":SharpDevelop">
<Doozer name="Parser" class="ICSharpCode.SharpDevelop.Parser.ParserDoozer"/>
</Import>
</Runtime>
<Path name="/SharpDevelop/Services">
<Service id="ICSharpCode.SharpDevelop.Parser.IGlobalAssemblyCacheService"
class="ICSharpCode.SharpDevelop.Parser.GlobalAssemblyCacheService"/>
<Service id="ICSharpCode.SharpDevelop.Parser.IParserService"
class="ICSharpCode.SharpDevelop.Parser.ParserService"/>
<Service id="ICSharpCode.SharpDevelop.IFileService"
class="ICSharpCode.SharpDevelop.Workbench.FileService"/>
</Path>
<Path name = "/SharpDevelop/Workbench/Ambiences">
<Class id = ".NET"
class = "ICSharpCode.SharpDevelop.NetAmbience"/>
@ -1066,7 +1076,7 @@ @@ -1066,7 +1076,7 @@
<ToolbarItem id = "ChooseLayout"
type = "ComboBox"
class = "ICSharpCode.SharpDevelop.Gui.Workbench.ChooseLayoutCommand" />
class = "ICSharpCode.SharpDevelop.Workbench.ChooseLayoutCommand" />
<ToolbarItem id="NavigationSeparator" type="Separator"/>
<Condition name="CanNavigateBack" action="Disable">
@ -2243,18 +2253,6 @@ @@ -2243,18 +2253,6 @@
class = "ICSharpCode.SharpDevelop.Gui.ToggleConsoleWordWrapCommand"/>
</Path>
<Path name="/SharpDevelop/Services/ParserService/SingleFileGacReferences">
<String id = "System" text = "System"/>
<String id = "System.Core" text = "System.Core"/>
<String id = "System.Data" text = "System.Data"/>
<String id = "System.Data.DataSetExtensions" text = "System.Data.DataSetExtensions"/>
<String id = "System.Drawing" text = "System.Drawing"/>
<String id = "System.Web" text = "System.Web"/>
<String id = "System.Windows.Forms" text = "System.Windows.Forms"/>
<String id = "System.Xml" text = "System.Xml"/>
<String id = "System.Xml.Linq" text = "System.Xml.Linq"/>
</Path>
<Path name = "/SharpDevelop/BackendBindings/TemplateCommands">
<Class id="AddDotNet35ReferencesIfTargetFrameworkIs35"
class="ICSharpCode.SharpDevelop.Project.Commands.AddDotNet35ReferencesIfTargetFrameworkIs35Command"/>

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

@ -360,8 +360,10 @@ @@ -360,8 +360,10 @@
<Compile Include="Src\Services\DisplayBinding\ISecondaryDisplayBinding.cs" />
<Compile Include="Src\Services\DisplayBinding\ShellExecuteDisplayBinding.cs" />
<Compile Include="Src\Services\File\FileChangeWatcher.cs" />
<Compile Include="Src\Services\File\IFileService.cs" />
<Compile Include="Src\Services\File\OpenedFile.cs" />
<Compile Include="Src\Services\File\RecentOpen.cs" />
<Compile Include="Src\Services\IMessageLoop.cs" />
<Compile Include="Src\Services\LanguageBinding\AggregatedLanguageBinding.cs" />
<Compile Include="Src\Services\LanguageBinding\DefaultLanguageBinding.cs" />
<Compile Include="Src\Services\LanguageBinding\ILanguageBinding.cs" />
@ -377,13 +379,11 @@ @@ -377,13 +379,11 @@
<Compile Include="Src\Services\MimeTypeDetection.cs" />
<Compile Include="Src\Services\ParserService\AssemblyParserService.cs" />
<Compile Include="Src\Services\ParserService\DomAssemblyName.cs" />
<Compile Include="Src\Services\ParserService\Fusion.cs" />
<Compile Include="Src\Services\ParserService\GacInterop.cs" />
<Compile Include="Src\Services\ParserService\ParsedFileListener.cs" />
<Compile Include="Src\Services\ParserService\IGlobalAssemblyCacheService.cs" />
<Compile Include="Src\Services\ParserService\IParserService.cs" />
<Compile Include="Src\Services\ParserService\IParser.cs" />
<Compile Include="Src\Services\ParserService\ParseInformation.cs" />
<Compile Include="Src\Services\ParserService\LoadSolutionProjects.cs" />
<Compile Include="Src\Services\ParserService\ParserService.cs" />
<Compile Include="Src\Services\ParserService\SharpDevelopSolutionSnapshot.cs" />
<Compile Include="Src\Services\ProjectService\CompileModifiedProjectsOnly.cs" />
<Compile Include="Src\Services\ProjectService\SolutionConfigurationEventHandler.cs" />
@ -578,8 +578,6 @@ @@ -578,8 +578,6 @@
<Compile Include="Src\Gui\Pads\ProjectBrowser\Commands\ToolbarCommands.cs" />
<Compile Include="Src\Services\ProjectBinding\ProjectBindingDescriptor.cs" />
<Compile Include="Src\Services\DisplayBinding\DisplayBindingDescriptor.cs" />
<Compile Include="Src\Services\ParserService\Doozer\ParserDoozer.cs" />
<Compile Include="Src\Services\ParserService\Doozer\ParserDescriptor.cs" />
<Compile Include="Src\Gui\XmlForms\Lib\IPropertyValueCreator.cs" />
<Compile Include="Src\Gui\XmlForms\Lib\IStringValueFilter.cs" />
<Compile Include="Src\Gui\XmlForms\Lib\StringWrapper.cs" />
@ -734,6 +732,7 @@ @@ -734,6 +732,7 @@
<Compile Include="Src\Services\ProjectService\ProjectLoader.cs" />
<Compile Include="Src\Util\DotnetDetection.cs" />
<Compile Include="Src\Util\FakeXmlViewContent.cs" />
<Compile Include="Src\Util\MultiDictionary.cs" />
<Compile Include="Src\Util\ReactiveExtensions.cs" />
<Compile Include="Src\Util\SharpDevelopServiceContainer.cs" />
<Compile Include="Src\Util\TreeNode.cs" />
@ -784,8 +783,6 @@ @@ -784,8 +783,6 @@
<Compile Include="Src\Util\UnclosableStream.cs" />
<Compile Include="Src\Util\WeakCollection.cs" />
<Compile Include="Src\Util\WindowsFormsPrinting.cs" />
<Compile Include="Src\Util\WpfSynchronizeInvoke.cs" />
<Compile Include="Src\Util\WorkerThread.cs" />
<EmbeddedResource Include="Resources\DefaultManifest.manifest" />
<EmbeddedResource Include="Src\Gui\Dialogs\ExtractInterfaceDialog.resx">
<DependentUpon>ExtractInterfaceDialog.cs</DependentUpon>

2
src/Main/Base/Project/Src/Editor/Commands/SymbolUnderCaretMenuCommand.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands @@ -27,7 +27,7 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands
public void Run(ITextEditor editor, int caretOffset)
{
var location = editor.Document.GetLocation(caretOffset);
var resolveResult = ParserService.Resolve(editor.FileName, location, editor.Document);
var resolveResult = SD.ParserService.Resolve(editor, location);
RunImpl(editor, editor.Caret.Offset, resolveResult);
}

3
src/Main/Base/Project/Src/Editor/IDocumentBaseVersionProvider.cs

@ -49,8 +49,7 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -49,8 +49,7 @@ namespace ICSharpCode.SharpDevelop.Editor
{
this.watcher = new FileSystemWatcher(repositoryRoot);
if (WorkbenchSingleton.Workbench != null)
watcher.SynchronizingObject = WorkbenchSingleton.Workbench.SynchronizingObject;
watcher.SynchronizingObject = SD.MainThread.SynchronizingObject;
WorkbenchSingleton.MainWindow.Activated += MainWindowActivated;

2
src/Main/Base/Project/Src/Editor/ToolTipRequestEventArgs.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.SharpDevelop.Editor @@ -45,7 +45,7 @@ namespace ICSharpCode.SharpDevelop.Editor
get {
if (!resolveResultInitialized) {
if (InDocument)
resolveResult = ParserService.Resolve(this.Editor.FileName, this.LogicalPosition, this.Editor.Document);
resolveResult = SD.ParserService.Resolve(this.Editor, this.LogicalPosition);
resolveResultInitialized = true;
}
return resolveResult;

6
src/Main/Base/Project/Src/Gui/Dialogs/GotoDialog.cs

@ -38,14 +38,14 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -38,14 +38,14 @@ namespace ICSharpCode.SharpDevelop.Gui
{
InitializeComponent();
FormLocationHelper.ApplyWindow(this, "ICSharpCode.SharpDevelop.Gui.GotoDialog.Bounds", true);
ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded;
SD.ParserService.LoadSolutionProjectsThreadEnded += ParserService_LoadSolutionProjectsThreadEnded;
textBox.Focus();
}
protected override void OnClosed(EventArgs e)
{
Instance = null;
ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded;
SD.ParserService.LoadSolutionProjectsThreadEnded -= ParserService_LoadSolutionProjectsThreadEnded;
base.OnClosed(e);
}
@ -163,7 +163,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -163,7 +163,7 @@ namespace ICSharpCode.SharpDevelop.Gui
{
ITextEditor editor = GetEditor();
if (editor != null) {
IParsedFile parseInfo = ParserService.GetExistingParsedFile(editor.FileName);
IParsedFile parseInfo = SD.ParserService.GetExistingParsedFile(editor.FileName);
if (parseInfo != null) {
foreach (IUnresolvedTypeDefinition c in parseInfo.TopLevelTypeDefinitions) {
AddAllMembersMatchingText(c, text);

3
src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs

@ -393,8 +393,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -393,8 +393,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (!String.IsNullOrEmpty(binaryFileName))
File.Copy(binaryFileName, parsedFileName);
else
File.WriteAllText(parsedFileName, parsedContent, ParserService.DefaultFileEncoding);
ParserService.ParseFileAsync(FileName.Create(parsedFileName), new StringTextSource(parsedContent)).FireAndForget();
File.WriteAllText(parsedFileName, parsedContent, SD.FileService.DefaultFileEncoding);
} else {
if (!String.IsNullOrEmpty(binaryFileName)) {
LoggingService.Warn("binary file was skipped");

5
src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/TaskListOptionsl.xaml.cs

@ -23,8 +23,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels @@ -23,8 +23,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
public TaskListXaml()
{
InitializeComponent();
string[] tokens = ParserService.TaskListTokens;
foreach (var token in tokens) {
foreach (var token in SD.ParserService.TaskListTokens) {
listView.Items.Add(token);
};
}
@ -80,7 +79,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels @@ -80,7 +79,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
tokens.Add(text);
}
}
ParserService.TaskListTokens = tokens.ToArray();
SD.ParserService.TaskListTokens = tokens.ToArray();
return true;
}
}

2
src/Main/Base/Project/Src/Gui/Dialogs/ReferenceDialog/GacReferencePanel.cs

@ -442,7 +442,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -442,7 +442,7 @@ namespace ICSharpCode.SharpDevelop.Gui
protected virtual IList<DomAssemblyName> GetCacheContent()
{
return GacInterop.GetGacAssemblyFullNames()
return SD.GlobalAssemblyCache.GetGacAssemblyFullNames()
.Where(name => !name.ShortName.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
.ToList();
}

4
src/Main/Base/Project/Src/Gui/Dialogs/WordCountDialog.cs

@ -53,7 +53,9 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -53,7 +53,9 @@ namespace ICSharpCode.SharpDevelop.Gui
{
if (!File.Exists(filename)) return null;
return GetReport(filename, ParserService.GetParseableFileContent(filename).CreateReader());
using (var reader = SD.FileService.GetFileContent(filename).CreateReader()) {
return GetReport(filename, reader);
}
}
Report GetReport(IViewContent content, TextReader reader)

5
src/Main/Base/Project/Src/Gui/IWorkbench.cs

@ -21,11 +21,6 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -21,11 +21,6 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
IWin32Window MainWin32Window { get; }
/// <summary>
/// Object for executing methods on the main thread.
/// </summary>
ISynchronizeInvoke SynchronizingObject { get; }
/// <summary>
/// The main window.
/// </summary>

7
src/Main/Base/Project/Src/Gui/Pads/DefinitionViewPad.cs

@ -40,7 +40,8 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -40,7 +40,8 @@ namespace ICSharpCode.SharpDevelop.Gui
ctl = Editor.AvalonEdit.AvalonEditTextEditorAdapter.CreateAvalonEditInstance();
ctl.IsReadOnly = true;
ctl.MouseDoubleClick += OnDoubleClick;
ParserService.ParserUpdateStepFinished += OnParserUpdateStep;
throw new NotImplementedException();
//ParserService.ParserUpdateStepFinished += OnParserUpdateStep;
ctl.IsVisibleChanged += delegate { UpdateTick(null); };
}
@ -49,7 +50,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -49,7 +50,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public override void Dispose()
{
ParserService.ParserUpdateStepFinished -= OnParserUpdateStep;
//ParserService.ParserUpdateStepFinished -= OnParserUpdateStep;
ctl.Document = null;
base.Dispose();
}
@ -95,7 +96,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -95,7 +96,7 @@ namespace ICSharpCode.SharpDevelop.Gui
// don't resolve when an unrelated file was changed
if (e != null && editor.FileName != e.FileName) return null;
return ParserService.ResolveAsync(editor.FileName, editor.Caret.Location, editor.Document);
return SD.ParserService.ResolveAsync(editor.FileName, editor.Caret.Location, editor.Document);
}
DomRegion oldPosition;

4
src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/Commands/ReferenceFolderNodeCommands.cs

@ -68,7 +68,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -68,7 +68,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
}
// Update code completion.
ParserService.ParseFileAsync(FileName.Create(webReference.WebProxyFileName)).FireAndForget();
SD.ParserService.ParseFileAsync(FileName.Create(webReference.WebProxyFileName), parentProject: url.Project).FireAndForget();
}
} catch (WebException ex) {
MessageService.ShowException(ex, String.Format(StringParser.Parse("${res:ICSharpCode.SharpDevelop.Commands.ProjectBrowser.RefreshWebReference.ReadServiceDescriptionError}"), url.UpdateFromURL));
@ -125,7 +125,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands @@ -125,7 +125,7 @@ namespace ICSharpCode.SharpDevelop.Project.Commands
AddWebReferenceToProjectBrowser(node, refDialog.WebReference);
// Add proxy to code completion.
ParserService.ParseFileAsync(FileName.Create(refDialog.WebReference.WebProxyFileName)).FireAndForget();
SD.ParserService.ParseFileAsync(FileName.Create(refDialog.WebReference.WebProxyFileName)).FireAndForget();
node.Project.Save();
}

2
src/Main/Base/Project/Src/Gui/Pads/PropertyPad/PropertyPad.cs

@ -413,7 +413,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -413,7 +413,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (gridItem != null) {
Type component = gridItem.PropertyDescriptor.ComponentType;
if (component != null) {
ICompilation compilation = ParserService.GetCompilation(ProjectService.CurrentProject);
ICompilation compilation = SD.ParserService.GetCompilation(ProjectService.CurrentProject);
IType componentType = compilation.FindType(component);
IProperty property = componentType.GetProperties(p => p.Name == gridItem.PropertyDescriptor.Name).FirstOrDefault();
if (property != null)

6
src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPad.cs

@ -129,7 +129,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -129,7 +129,7 @@ namespace ICSharpCode.SharpDevelop.Gui
contentPanel.Controls.Add(taskView);
string[] tokens = ParserService.TaskListTokens;
IReadOnlyList<string> tokens = SD.ParserService.TaskListTokens;
foreach (string token in tokens)
{
@ -219,7 +219,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -219,7 +219,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (WorkbenchSingleton.Workbench.ActiveViewContent == null)
return null;
IParsedFile parseInfo = ParserService.GetExistingParsedFile(WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName);
IParsedFile parseInfo = SD.ParserService.GetExistingParsedFile(WorkbenchSingleton.Workbench.ActiveViewContent.PrimaryFileName);
if (parseInfo != null) {
IPositionable positionable = WorkbenchSingleton.Workbench.ActiveViewContent as IPositionable;
if (positionable != null) {
@ -236,7 +236,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -236,7 +236,7 @@ namespace ICSharpCode.SharpDevelop.Gui
// Tasks are created by parsing, so the parse information for item.FileName should already be present.
// If they aren't, that's because the file might have been deleted/renamed in the meantime.
// We use GetExistingParseInformation to avoid trying to parse a file that might have been deleted/renamed.
IParsedFile parseInfo = ParserService.GetExistingParsedFile(item.FileName);
IParsedFile parseInfo = SD.ParserService.GetExistingParsedFile(item.FileName);
if (parseInfo != null) {
var c = parseInfo.GetInnermostTypeDefinition(item.Line, item.Column);
if (c != null) return c;

5
src/Main/Base/Project/Src/Gui/Pads/TaskList/TaskListPadCommands.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
@ -76,9 +77,9 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -76,9 +77,9 @@ namespace ICSharpCode.SharpDevelop.Gui
public class TaskListTokensBuilder
{
public static ShowTaskListTokenButton[] BuildItems(string[] tokens)
public static ShowTaskListTokenButton[] BuildItems(IReadOnlyList<string> tokens)
{
ShowTaskListTokenButton[] buttons = new ShowTaskListTokenButton[tokens.Length];
ShowTaskListTokenButton[] buttons = new ShowTaskListTokenButton[tokens.Count];
for (int i = 0; i < buttons.Length; i++)
{

72
src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using ICSharpCode.Core;
@ -70,7 +71,6 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -70,7 +71,6 @@ namespace ICSharpCode.SharpDevelop.Gui
DisplayBindingService.InitializeService();
FileService.InitializeService();
ParserService.InitializeParserService();
TaskService.Initialize();
Bookmarks.BookmarkManager.Initialize();
Project.CustomToolsService.Initialize();
@ -80,7 +80,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -80,7 +80,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (messageService != null) {
messageService.DialogOwner = workbench.MainWin32Window;
Debug.Assert(messageService.DialogOwner != null);
messageService.DialogSynchronizeInvoke = workbench.SynchronizingObject;
messageService.DialogSynchronizeInvoke = SD.MainThread.SynchronizingObject;
}
workbench.Initialize();
@ -133,7 +133,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -133,7 +133,7 @@ namespace ICSharpCode.SharpDevelop.Gui
if (workbench == null)
return false; // unit test mode, don't crash
else
return workbench.SynchronizingObject.InvokeRequired;
return SD.MainThread.InvokeRequired;
}
}
@ -166,13 +166,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -166,13 +166,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static R SafeThreadFunction<R>(Func<R> method)
{
// InvokeRequired test is necessary so that we don't run other actions in the message queue
// when we're already running on the main thread (unexpected reentrancy)
ISynchronizeInvoke si = workbench.SynchronizingObject;
if (si.InvokeRequired)
return (R)workbench.SynchronizingObject.Invoke(method, emptyObjectArray);
else
return method();
return SD.MainThread.InvokeIfRequired(method);
}
/// <summary>
@ -182,11 +176,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -182,11 +176,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static R SafeThreadFunction<A, R>(Func<A, R> method, A arg1)
{
ISynchronizeInvoke si = workbench.SynchronizingObject;
if (si.InvokeRequired)
return (R)si.Invoke(method, new object[] { arg1 });
else
return method(arg1);
return SD.MainThread.InvokeIfRequired(() => method(arg1));
}
/// <summary>
@ -196,11 +186,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -196,11 +186,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static void SafeThreadCall(Action method)
{
ISynchronizeInvoke si = workbench.SynchronizingObject;
if (si.InvokeRequired)
si.Invoke(method, emptyObjectArray);
else
method();
SD.MainThread.InvokeIfRequired(method);
}
/// <summary>
@ -210,11 +196,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -210,11 +196,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static void SafeThreadCall<A>(Action<A> method, A arg1)
{
ISynchronizeInvoke si = workbench.SynchronizingObject;
if (si.InvokeRequired)
si.Invoke(method, new object[] { arg1 });
else
method(arg1);
SD.MainThread.InvokeIfRequired(() => method(arg1));
}
/// <summary>
@ -224,11 +206,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -224,11 +206,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static void SafeThreadCall<A, B>(Action<A, B> method, A arg1, B arg2)
{
ISynchronizeInvoke si = workbench.SynchronizingObject;
if (si.InvokeRequired)
si.Invoke(method, new object[] { arg1, arg2 });
else
method(arg1, arg2);
SD.MainThread.InvokeIfRequired(() => method(arg1, arg2));
}
/// <summary>
@ -238,11 +216,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -238,11 +216,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static void SafeThreadCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3)
{
ISynchronizeInvoke si = workbench.SynchronizingObject;
if (si.InvokeRequired)
si.Invoke(method, new object[] { arg1, arg2, arg3 });
else
method(arg1, arg2, arg3);
SD.MainThread.InvokeIfRequired(() => method(arg1, arg2, arg3));
}
/// <summary>
@ -250,7 +224,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -250,7 +224,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static void SafeThreadAsyncCall(Action method)
{
workbench.SynchronizingObject.BeginInvoke(method, emptyObjectArray);
SD.MainThread.InvokeAsync(method).FireAndForget();
}
/// <summary>
@ -258,7 +232,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -258,7 +232,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static void SafeThreadAsyncCall<A>(Action<A> method, A arg1)
{
workbench.SynchronizingObject.BeginInvoke(method, new object[] { arg1 });
SD.MainThread.InvokeAsync(() => method(arg1)).FireAndForget();
}
/// <summary>
@ -266,7 +240,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -266,7 +240,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static void SafeThreadAsyncCall<A, B>(Action<A, B> method, A arg1, B arg2)
{
workbench.SynchronizingObject.BeginInvoke(method, new object[] { arg1, arg2 });
SD.MainThread.InvokeAsync(() => method(arg1, arg2)).FireAndForget();
}
/// <summary>
@ -274,30 +248,16 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -274,30 +248,16 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public static void SafeThreadAsyncCall<A, B, C>(Action<A, B, C> method, A arg1, B arg2, C arg3)
{
workbench.SynchronizingObject.BeginInvoke(method, new object[] { arg1, arg2, arg3 });
SD.MainThread.InvokeAsync(() => method(arg1, arg2, arg3)).FireAndForget();
}
/// <summary>
/// Calls a method on the GUI thread, but delays the call a bit.
/// </summary>
public static void CallLater(TimeSpan delay, Action method)
public static async void CallLater(TimeSpan delay, Action method)
{
int delayMilliseconds = (int)delay.TotalMilliseconds;
if (delayMilliseconds < 0)
throw new ArgumentOutOfRangeException("delay", delay, "Value must be positive");
if (method == null)
throw new ArgumentNullException("method");
SafeThreadAsyncCall(
delegate {
Timer t = new Timer();
t.Interval = Math.Max(1, delayMilliseconds);
t.Tick += delegate {
t.Stop();
t.Dispose();
method();
};
t.Start();
});
await Task.Delay(delay).ConfigureAwait(false);
SD.MainThread.InvokeAsync(method).FireAndForget();
}
#endregion

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

@ -372,7 +372,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -372,7 +372,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
File.Copy(file.BinaryFileName,fileName);
} else {
// Textual content
StreamWriter sr = new StreamWriter(File.Create(fileName), ParserService.DefaultFileEncoding);
StreamWriter sr = new StreamWriter(File.Create(fileName), SD.FileService.DefaultFileEncoding);
string fileContent = StringParser.Parse(file.Content, new StringTagPair("ProjectName", projectCreateInformation.ProjectName), new StringTagPair("FileName", fileName));
fileContent = StringParser.Parse(fileContent);
if (SD.EditorControlService.GlobalOptions.IndentationString != "\t") {

11
src/Main/Base/Project/Src/Project/AbstractProject.cs

@ -15,6 +15,7 @@ using ICSharpCode.NRefactory.TypeSystem; @@ -15,6 +15,7 @@ using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.OptionPanels;
using ICSharpCode.SharpDevelop.Parser;
namespace ICSharpCode.SharpDevelop.Project
{
@ -409,6 +410,16 @@ namespace ICSharpCode.SharpDevelop.Project @@ -409,6 +410,16 @@ namespace ICSharpCode.SharpDevelop.Project
}
}
public virtual event EventHandler<ParseInformationEventArgs> ParseInformationUpdated {
add {}
remove {}
}
public virtual void OnParseInformationUpdated(ParseInformationEventArgs args)
{
throw new NotSupportedException();
}
/// <summary>
/// Creates a new projectItem for the passed itemType
/// </summary>

13
src/Main/Base/Project/Src/Project/CompilableProject.cs

@ -379,6 +379,19 @@ namespace ICSharpCode.SharpDevelop.Project @@ -379,6 +379,19 @@ namespace ICSharpCode.SharpDevelop.Project
return GetParseProjectContentContainer().ProjectContent;
}
}
public override void OnParseInformationUpdated(ParseInformationEventArgs args)
{
GetParseProjectContentContainer().ParseInformationUpdated(args.OldParsedFile, args.NewParsedFile);
// OnParseInformationUpdated is called inside a lock, but we don't want to raise the event inside that lock.
// To ensure events are raised in the same order, we always invoke on the main thread.
SD.MainThread.InvokeAsync(
delegate {
ParseInformationUpdated(null, args);
});
}
public override event EventHandler<ParseInformationEventArgs> ParseInformationUpdated = delegate {};
#endregion
}
}

2
src/Main/Base/Project/Src/Project/CustomTool.cs

@ -201,7 +201,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -201,7 +201,7 @@ namespace ICSharpCode.SharpDevelop.Project
},
outputFileName, FileErrorPolicy.Inform);
EnsureOutputFileIsInProject(baseItem, outputFileName);
ParserService.ParseAsync(FileName.Create(outputFileName), new StringTextSource(codeOutput)).FireAndForget();
SD.ParserService.ParseAsync(FileName.Create(outputFileName), new StringTextSource(codeOutput)).FireAndForget();
}
public void GenerateCodeDomAsync(FileProjectItem baseItem, string outputFileName, Func<CodeCompileUnit> func)

12
src/Main/Base/Project/Src/Project/IProject.cs

@ -12,6 +12,7 @@ using System.Xml.Linq; @@ -12,6 +12,7 @@ using System.Xml.Linq;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
namespace ICSharpCode.SharpDevelop.Project
{
@ -304,6 +305,17 @@ namespace ICSharpCode.SharpDevelop.Project @@ -304,6 +305,17 @@ namespace ICSharpCode.SharpDevelop.Project
/// An object that can be used to perform the search; or null if this project does not support symbol searches.
/// </returns>
Refactoring.ISymbolSearch PrepareSymbolSearch(IEntity entity);
/// <summary>
/// Occurs whenever parse information for this project was updated. This event is raised on the main thread.
/// </summary>
event EventHandler<ParseInformationEventArgs> ParseInformationUpdated;
/// <summary>
/// Notifies the project that the parse information was updated.
/// This method is called by the parser service <b>within a per-file lock</b>.
/// </summary>
void OnParseInformationUpdated(ParseInformationEventArgs args);
}
/// <summary>

3
src/Main/Base/Project/Src/Project/ProjectChangeWatcher.cs

@ -72,8 +72,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -72,8 +72,7 @@ namespace ICSharpCode.SharpDevelop.Project
try {
if (watcher == null) {
watcher = new FileSystemWatcher();
if (WorkbenchSingleton.Workbench != null)
watcher.SynchronizingObject = WorkbenchSingleton.Workbench.SynchronizingObject;
watcher.SynchronizingObject = SD.MainThread.SynchronizingObject;
watcher.Changed += OnFileChangedEvent;
watcher.Created += OnFileChangedEvent;
watcher.Renamed += OnFileChangedEvent;

10
src/Main/Base/Project/Src/Refactoring/EditorRefactoringContext.cs

@ -76,7 +76,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -76,7 +76,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
{
lock (syncRoot) {
if (parseInformation == null)
parseInformation = ParserService.ParseAsync(this.FileName, this.TextSource);
parseInformation = SD.ParserService.ParseAsync(this.FileName, this.TextSource);
return parseInformation;
}
}
@ -86,6 +86,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -86,6 +86,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
/// </summary>
public ParseInformation GetParseInformation()
{
// waiting for the task is safe because we specified the text source in the ParseAsync call
return GetParseInformationAsync().Result;
}
@ -96,7 +97,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -96,7 +97,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
{
lock (syncRoot) {
if (compilation == null)
compilation = Task.FromResult(ParserService.GetCompilationForFile(this.FileName));
compilation = Task.FromResult(SD.ParserService.GetCompilationForFile(this.FileName));
return compilation;
}
}
@ -145,14 +146,11 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -145,14 +146,11 @@ namespace ICSharpCode.SharpDevelop.Refactoring
async Task<ResolveResult> ResolveCurrentSymbolAsync()
{
var parser = ParserService.GetParser(this.FileName);
if (parser == null)
return null;
var parseInfo = await GetParseInformationAsync().ConfigureAwait(false);
if (parseInfo == null)
return null;
var compilation = await GetCompilationAsync().ConfigureAwait(false);
return await Task.Run(() => ParserService.ResolveAsync(this.FileName, caretLocation, this.TextSource, CancellationToken.None)).ConfigureAwait(false);
return await Task.Run(() => SD.ParserService.ResolveAsync(this.FileName, caretLocation, this.TextSource, compilation)).ConfigureAwait(false);
}
/// <summary>

3
src/Main/Base/Project/Src/Services/File/FileChangeWatcher.cs

@ -134,8 +134,7 @@ namespace ICSharpCode.SharpDevelop @@ -134,8 +134,7 @@ namespace ICSharpCode.SharpDevelop
try {
if (watcher == null) {
watcher = new FileSystemWatcher();
if (WorkbenchSingleton.Workbench != null)
watcher.SynchronizingObject = WorkbenchSingleton.Workbench.SynchronizingObject;
watcher.SynchronizingObject = SD.MainThread.SynchronizingObject;
watcher.Changed += OnFileChangedEvent;
watcher.Created += OnFileChangedEvent;
watcher.Renamed += OnFileChangedEvent;

6
src/Main/Base/Project/Src/Services/File/FileService.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.SharpDevelop @@ -44,7 +44,7 @@ namespace ICSharpCode.SharpDevelop
PropertyService.SetNestedProperties("RecentOpen", recentOpen.ToProperties());
}
ProjectService.SolutionLoaded -= ProjectServiceSolutionLoaded;
ParserService.LoadSolutionProjectsThreadEnded -= ParserServiceLoadSolutionProjectsThreadEnded;
SD.ParserService.LoadSolutionProjectsThreadEnded -= ParserServiceLoadSolutionProjectsThreadEnded;
serviceInitialized = false;
}
@ -52,7 +52,7 @@ namespace ICSharpCode.SharpDevelop @@ -52,7 +52,7 @@ namespace ICSharpCode.SharpDevelop
{
if (!serviceInitialized) {
ProjectService.SolutionLoaded += ProjectServiceSolutionLoaded;
ParserService.LoadSolutionProjectsThreadEnded += ParserServiceLoadSolutionProjectsThreadEnded;
SD.ParserService.LoadSolutionProjectsThreadEnded += ParserServiceLoadSolutionProjectsThreadEnded;
serviceInitialized = true;
}
}
@ -278,7 +278,7 @@ namespace ICSharpCode.SharpDevelop @@ -278,7 +278,7 @@ namespace ICSharpCode.SharpDevelop
/// <param name="content">Content of the file to create</param>
public static IViewContent NewFile(string defaultName, string content)
{
return NewFile(defaultName, ParserService.DefaultFileEncoding.GetBytesWithPreamble(content));
return NewFile(defaultName, SD.FileService.DefaultFileEncoding.GetBytesWithPreamble(content));
}
/// <summary>

55
src/Main/Base/Project/Src/Services/File/IFileService.cs

@ -0,0 +1,55 @@ @@ -0,0 +1,55 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Text;
using System.Threading;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// File service.
/// </summary>
public interface IFileService
{
/// <summary>
/// Gets the default file encoding.
/// This property is thread-safe.
/// </summary>
Encoding DefaultFileEncoding { get; }
/// <summary>
/// Gets the content of the specified file.
/// If the file is currently open in SharpDevelop, retrieves a snapshot
/// of the editor content.
/// </summary>
/// <remarks>
/// This method is thread-safe. This method involves waiting for the main thread, so using it while
/// holding a lock can lead to deadlocks.
/// </remarks>
ITextSource GetFileContent(FileName fileName);
/// <inheritdoc cref="GetParseableFileContent(FileName)"/>
ITextSource GetFileContent(string fileName);
/// <summary>
/// Gets the file content for a file that is currently open.
/// Returns null if the file is not open.
/// </summary>
/// <remarks>
/// This method is thread-safe. This method involves waiting for the main thread, so using it while
/// holding a lock can lead to deadlocks.
/// </remarks>
ITextSource GetFileContentForOpenFile(FileName fileName);
/// <summary>
/// Gets the file content from disk, ignoring open files.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// </remarks>
ITextSource GetFileContentFromDisk(FileName fileName, CancellationToken cancellationToken = default(CancellationToken));
}
}

4
src/Main/Base/Project/Src/Services/File/OpenedFile.cs

@ -461,9 +461,9 @@ namespace ICSharpCode.SharpDevelop @@ -461,9 +461,9 @@ namespace ICSharpCode.SharpDevelop
// We discarded some information when closing the file,
// so we need to re-parse it.
if (File.Exists(this.FileName))
ParserService.ParseAsync(this.FileName).FireAndForget();
SD.ParserService.ParseAsync(this.FileName).FireAndForget();
else
ParserService.ClearParseInformation(this.FileName);
SD.ParserService.ClearParseInformation(this.FileName);
}
}
}

93
src/Main/Base/Project/Src/Services/IMessageLoop.cs

@ -0,0 +1,93 @@ @@ -0,0 +1,93 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// Represents a thread running a message loop.
/// </summary>
public interface IMessageLoop
{
/// <summary>
/// Gets the thread corresponding to this message loop.
/// </summary>
Thread Thread { get; }
/// <summary>
/// Gets the dispatcher for this message loop.
/// </summary>
Dispatcher Dispatcher { get; }
/// <summary>
/// Gets the synchronization context corresponding to this message loop.
/// </summary>
SynchronizationContext SynchronizationContext { get; }
/// <summary>
/// Gets the <see cref="ISynchronizeInvoke"/> implementation corresponding to this message loop.
/// </summary>
ISynchronizeInvoke SynchronizingObject { get; }
/// <summary>
/// Gets whether the current thread is different from the thread running this message loop.
/// </summary>
/// <remarks><c>InvokeRequired = !CheckAcess()</c></remarks>
bool InvokeRequired { get; }
/// <summary>
/// Gets whether the current thread is the same as the thread running this message loop.
/// </summary>
/// <remarks><c>CheckAccess() = !InvokeRequired</c></remarks>
bool CheckAccess();
/// <summary>
/// Throws an exception if the current thread is different from the thread running this message loop.
/// </summary>
void VerifyAccess();
/// <summary>
/// Invokes the specified callback on the message loop and waits for its completion.
/// If the current thread is the thread running the message loop, executes the callback
/// directly without pumping the message loop.
/// </summary>
void InvokeIfRequired(Action callback);
/// <inheritdoc see="Invoke(Action)"/>
void InvokeIfRequired(Action callback, DispatcherPriority priority);
/// <inheritdoc see="Invoke(Action)"/>
void InvokeIfRequired(Action callback, DispatcherPriority priority, CancellationToken cancellationToken);
/// <summary>
/// Invokes the specified callback, waits for its completion, and returns the result.
/// If the current thread is the thread running the message loop, executes the callback
/// directly without pumping the message loop.
/// </summary>
T InvokeIfRequired<T>(Func<T> callback);
/// <inheritdoc see="Invoke{T}(Func{T})"/>
T InvokeIfRequired<T>(Func<T> callback, DispatcherPriority priority);
/// <inheritdoc see="Invoke{T}(Func{T})"/>
T InvokeIfRequired<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken);
/// <summary>
/// Invokes the specified callback.
/// </summary>
/// <returns>Returns a task that is signalled when the execution of the callback is completed.</returns>
Task InvokeAsync(Action callback);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task InvokeAsync(Action callback, DispatcherPriority priority);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task<T> InvokeAsync<T>(Func<T> callback);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority);
/// <inheritdoc see="InvokeAsync(Action)"/>
Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken);
}
}

2
src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs

@ -70,7 +70,7 @@ namespace ICSharpCode.SharpDevelop @@ -70,7 +70,7 @@ namespace ICSharpCode.SharpDevelop
// ignore files opened as part of loading a solution.
ProjectService.SolutionLoading += ProjectService_SolutionLoading;
ParserService.LoadSolutionProjectsThreadEnded += LoadSolutionProjectsThreadEnded;
SD.ParserService.LoadSolutionProjectsThreadEnded += LoadSolutionProjectsThreadEnded;
FileService.FileRenamed += FileService_FileRenamed;
ProjectService.SolutionClosed += ProjectService_SolutionClosed;

11
src/Main/Base/Project/Src/Services/ParserService/DomAssemblyName.cs

@ -9,6 +9,7 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -9,6 +9,7 @@ namespace ICSharpCode.SharpDevelop.Parser
/// Similar to System.Reflection.AssemblyName, but does not raise an exception
/// on invalid assembly names. (See SD-1307)
/// </summary>
[Serializable]
public sealed class DomAssemblyName : IEquatable<DomAssemblyName>
{
readonly string fullAssemblyName;
@ -79,15 +80,5 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -79,15 +80,5 @@ namespace ICSharpCode.SharpDevelop.Parser
{
return other != null && fullAssemblyName == other.fullAssemblyName;
}
internal static DomAssemblyName[] Convert(System.Reflection.AssemblyName[] names)
{
if (names == null) return null;
DomAssemblyName[] n = new DomAssemblyName[names.Length];
for (int i = 0; i < names.Length; i++) {
n[i] = new DomAssemblyName(names[i].FullName);
}
return n;
}
}
}

30
src/Main/Base/Project/Src/Services/ParserService/IGlobalAssemblyCacheService.cs

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
namespace ICSharpCode.SharpDevelop.Parser
{
/// <summary>
/// Interface for global assembly cache service.
/// </summary>
public interface IGlobalAssemblyCacheService
{
/// <summary>
/// Gets whether the file name is within the GAC.
/// </summary>
bool IsGACAssembly(string fileName);
/// <summary>
/// Gets the names of all assemblies in the GAC.
/// </summary>
IEnumerable<DomAssemblyName> GetGacAssemblyFullNames();
/// <summary>
/// Gets the file name for an assembly stored in the GAC.
/// Returns null if the assembly cannot be found.
/// </summary>
string FindAssemblyInNetGac(DomAssemblyName reference);
}
}

23
src/Main/Base/Project/Src/Services/ParserService/IParser.cs

@ -2,17 +2,18 @@ @@ -2,17 +2,18 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Threading;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Project
namespace ICSharpCode.SharpDevelop.Parser
{
/// <summary>
/// Represents a language parser that produces ParseInformation
@ -23,10 +24,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -23,10 +24,7 @@ namespace ICSharpCode.SharpDevelop.Project
/// <summary>
/// Gets/Sets the tags used to identify tasks.
/// </summary>
string[] LexerTags {
get;
set;
}
IReadOnlyList<string> TaskListTokens { get; set; }
/// <summary>
/// Gets if the parser can parse the specified file.
@ -45,15 +43,20 @@ namespace ICSharpCode.SharpDevelop.Project @@ -45,15 +43,20 @@ namespace ICSharpCode.SharpDevelop.Project
/// Specifies whether full parse information were requested for this file.
/// If this parameter is false, only the ParsedFile and TagComments on the parse information need to be set.
/// </param>
/// <param name="parentProject">The parent project for this parse run.</param>
/// <param name="cancellationToken">Cancellation Token.</param>
/// <returns>The parse information representing the parse results.</returns>
/// <remarks>
/// SharpDevelop may call IParser.Parse in parallel; even on the same IParser instance
/// if there are two parallel parse requests for the same file. Parser implementations must be thread-safe.
/// The SharpDevelop parser service may call IParser.Parse in parallel;
/// even on the same IParser instance if there are two parallel parse requests for the same file.
/// Parser implementations must be thread-safe.
///
/// The SharpDevelop main thread is allowed to wait for a parse operation to finish; thus IParser
/// implementations must not invoke methods on the main thread and wait for their results,
/// as that would deadlock.
/// </remarks>
ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested);
ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested,
IProject parentProject, CancellationToken cancellationToken);
ResolveResult Resolve(ParseInformation parseInfo, TextLocation location, ICompilation compilation, CancellationToken cancellationToken);

291
src/Main/Base/Project/Src/Services/ParserService/IParserService.cs

@ -0,0 +1,291 @@ @@ -0,0 +1,291 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Parser
{
/// <summary>
/// Manages parse runs and caches ParseInformation.
/// </summary>
public interface IParserService
{
/// <summary>
/// Gets/Sets the task list tokens.
/// The getter of this property is thread-safe;
/// the setter must only be called on the main thread.
/// </summary>
IReadOnlyList<string> TaskListTokens { get; set; }
#region Load Solution Projects Thread
/// <summary>
/// Gets whether the solution is being loaded, or a major re-parse is happening
/// (e.g. after adding a project).
/// </summary>
/// <remarks>This property is only changed by the main thread.</remarks>
bool LoadSolutionProjectsThreadRunning { get; }
/// <summary>
/// This event is raised when the LoadSolutionProjectsThreadRunning property changes to <c>true</c>.
/// This always happens on the main thread.
/// </summary>
event EventHandler LoadSolutionProjectsThreadStarted;
/// <summary>
/// This event is raised when the LoadSolutionProjectsThreadRunning property changes to <c>false</c>.
/// This always happens on the main thread.
/// </summary>
event EventHandler LoadSolutionProjectsThreadEnded; // TODO: rename to finished
#endregion
#region GetCompilation
/// <summary>
/// Gets or creates a compilation for the specified project.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// This method never returns null - in case of errors, a dummy compilation is created.
/// </remarks>
ICompilation GetCompilation(IProject project);
/// <summary>
/// Gets or creates a compilation for the project that contains the specified file.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// This method never returns null - in case of errors, a dummy compilation is created.
/// </remarks>
ICompilation GetCompilationForFile(FileName fileName);
/// <summary>
/// Gets a snapshot of the current compilations
/// This method is useful when a consistent snapshot across multiple compilations is needed.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// </remarks>
SharpDevelopSolutionSnapshot GetCurrentSolutionSnapshot();
/// <summary>
/// Invalidates the current solution snapshot, causing
/// the next <see cref="GetCurrentSolutionSnapshot()"/> call to create a new one.
/// This method needs to be called whenever IProject.ProjectContent changes.
/// </summary>
/// <remarks>
/// This method is thread-safe.
/// </remarks>
void InvalidateCurrentSolutionSnapshot();
#endregion
#region GetExistingParsedFile
/// <summary>
/// Gets the unresolved type system for the specified file.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="version">
/// Optional: requested version of the file.
/// If this parameter is specified and the existing parsed file belongs to a different version,
/// this method will return null.
/// </param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns>
/// Returns the IParsedFile for the specified file,
/// or null if the file has not been parsed yet.
/// </returns>
/// <remarks>This method is thread-safe.</remarks>
IParsedFile GetExistingParsedFile(FileName fileName, ITextSourceVersion version = null, IProject parentProject = null);
/// <summary>
/// Gets full parse information for the specified file, if it is available.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="version">
/// Optional: requested version of the file.
/// If this parameter is specified and the existing parsed file belongs to a different version,
/// this method will return null.
/// </param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns>
/// If only the IParsedFile is available (non-full parse information), this method returns null.
/// </returns>
ParseInformation GetCachedParseInformation(FileName fileName, ITextSourceVersion version = null, IProject parentProject = null);
#endregion
#region Parse
/// <summary>
/// Parses the specified file.
/// Produces full parse information.
/// </summary>
/// <param name="fileName">Name of the file to parse</param>
/// <param name="fileContent">Optional: Content of the file to parse.</param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns>
/// Returns the ParseInformation for the specified file, or null if the file cannot be parsed.
/// For files currently open in an editor, this method does not necessary reparse, but may return
/// an existing cached parse information (but only if it's still up-to-date).
/// </returns>
/// <remarks>
/// This method is thread-safe.
/// <para>
/// If <paramref name="fileContent"/> is null, this method will block and wait for the main thread
/// to retrieve the latest file content. This can cause deadlocks if this method is called within a lock.
/// </para>
/// <para>
/// If <paramref name="fileContent"/> not null, the exact file version specified will be parsed.
/// This method will not wait for the main thread in that case.
/// If the specified version is older than the latest version, the old version will be parsed
/// and returned, but the old parse information will not be registered.
/// </para>
/// </remarks>
ParseInformation Parse(FileName fileName, ITextSource fileContent = null, IProject parentProject = null,
CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Parses the specified file.
/// This method does not request full parse information.
/// </summary>
/// <param name="fileName">Name of the file to parse</param>
/// <param name="fileContent">Optional: Content of the file to parse.</param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns>
/// Returns the IParsedFile for the specified file, or null if the file cannot be parsed.
/// For files currently open in an editor, this method does not necessarily reparse, but may return
/// the existing IParsedFile (but only if it's still up-to-date).
/// </returns>
/// <remarks><inheritdoc cref="Parse"/></remarks>
IParsedFile ParseFile(FileName fileName, ITextSource fileContent = null, IProject parentProject = null,
CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Parses the specified file on a background thread.
/// Produces full parse information.
/// </summary>
/// <param name="fileName">Name of the file to parse</param>
/// <param name="fileContent">Optional: Content of the file to parse.</param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns><inheritdoc cref="Parse"/></returns>
/// <remarks>
/// This method is thread-safe.
/// <para>
/// If <paramref name="fileContent"/> is null, the task wait for the main thread
/// to retrieve the latest file content.
/// This means that waiting for the task can cause deadlocks. (however, using C# 5 <c>await</c> is safe)
/// </para>
/// <para>
/// If <paramref name="fileContent"/> not null, the exact file version specified will be parsed.
/// This method will not wait for the main thread in that case.
/// If the specified version is older than the latest version, the old version will be parsed
/// and returned, but the old parse information will not be registered.
/// </para>
/// </remarks>
Task<ParseInformation> ParseAsync(FileName fileName, ITextSource fileContent = null, IProject parentProject = null,
CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Parses the specified file on a background thread.
/// This method does not request full parse information.
/// </summary>
/// <param name="fileName">Name of the file to parse</param>
/// <param name="fileContent">Optional: Content of the file to parse.</param>
/// <param name="parentProject">
/// Optional: If the file is part of multiple projects, specifies
/// which parsed version of the file to return (for example, different project settings
/// can cause the file to be parsed differently).
/// </param>
/// <returns><inheritdoc cref="ParseFile"/></returns>
/// <remarks><inheritdoc cref="ParseAsync"/></remarks>
Task<IParsedFile> ParseFileAsync(FileName fileName, ITextSource fileContent = null, IProject parentProject = null,
CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region Resolve
ResolveResult Resolve(ITextEditor editor, TextLocation location,
ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken));
ResolveResult Resolve(FileName fileName, TextLocation location,
ITextSource fileContent = null, ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken));
Task<ResolveResult> ResolveAsync(FileName fileName, TextLocation location,
ITextSource fileContent = null, ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken));
Task FindLocalReferencesAsync(FileName fileName, IVariable variable, Action<Reference> callback,
ITextSource fileContent = null, ICompilation compilation = null,
CancellationToken cancellationToken = default(CancellationToken));
#endregion
#region Parsed File Listeners
/// <summary>
/// Gets whether a parser is registered for the specified file name.
/// </summary>
bool HasParser(FileName fileName);
/// <summary>
/// Clears the cached parse information.
/// If the file does not belong to any project, this also clears the cached type system.
/// </summary>
void ClearParseInformation(FileName fileName);
/// <summary>
/// Adds a project that owns the file and wishes to receive parse information.
/// </summary>
/// <param name="fileName">Name of the file contained in the project.</param>
/// <param name="project">The parent project of the file.</param>
/// <param name="startAsyncParse">
/// Whether to start an asynchronous parse operation for the specified file.
/// </param>
/// <param name="isLinkedFile">
/// Specified whether the file is linked within the project, i.e. likely also belongs to another project.
/// The parser services tries to use the project that contains the file directly (non-linked)
/// as the primary parent project.
/// </param>
void AddOwnerProject(FileName fileName, IProject project, bool startAsyncParse, bool isLinkedFile);
/// <summary>
/// Removes a project from the owners of the file.
/// This method invokes <c>project.UpdateParseInformation(existingParsedFile, null);</c>.
/// (unless existingParsedFile==null)
/// </summary>
void RemoveOwnerProject(FileName fileName, IProject project);
/// <summary>
/// Occurs whenever parse information was updated. This event is raised on the main thread.
/// </summary>
event EventHandler<ParseInformationEventArgs> ParseInformationUpdated;
#endregion
}
}

13
src/Main/Base/Project/Src/Services/ParserService/ParseInformationEventArgs.cs

@ -6,11 +6,13 @@ using System.Diagnostics; @@ -6,11 +6,13 @@ using System.Diagnostics;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Parser
{
public class ParseInformationEventArgs : EventArgs
{
IProject parentProject;
IParsedFile oldParsedFile;
ParseInformation newParseInformation;
@ -23,6 +25,14 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -23,6 +25,14 @@ namespace ICSharpCode.SharpDevelop.Parser
}
}
/// <summary>
/// Gets the parent project for this parse information.
/// Returns null if the parse information is not associated with any project.
/// </summary>
public IProject ParentProject {
get { return parentProject; }
}
/// <summary>
/// The old parsed file.
/// Returns null if no old parse information exists (first parse run).
@ -57,13 +67,14 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -57,13 +67,14 @@ namespace ICSharpCode.SharpDevelop.Parser
get { return this.NewParsedFile; }
}
public ParseInformationEventArgs(IParsedFile oldParsedFile, ParseInformation newParseInformation)
public ParseInformationEventArgs(IProject parentProject, IParsedFile oldParsedFile, ParseInformation newParseInformation)
{
if (oldParsedFile == null && newParseInformation == null)
throw new ArgumentNullException();
if (oldParsedFile != null && newParseInformation != null) {
Debug.Assert(FileUtility.IsEqualFileName(oldParsedFile.FileName, newParseInformation.FileName));
}
this.parentProject = parentProject;
this.oldParsedFile = oldParsedFile;
this.newParseInformation = newParseInformation;
}

42
src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs

@ -26,7 +26,6 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -26,7 +26,6 @@ namespace ICSharpCode.SharpDevelop.Parser
/// </summary>
readonly object lockObj = new object();
readonly ParsedFileListener myListener;
IProjectContent projectContent;
IAssemblyReference[] references = { MinimalCorlib.Instance };
bool initializing;
@ -38,19 +37,18 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -38,19 +37,18 @@ namespace ICSharpCode.SharpDevelop.Parser
throw new ArgumentNullException("project");
this.project = project;
this.projectContent = initialProjectContent.SetAssemblyName(project.AssemblyName);
this.myListener = new ParsedFileListener(OnParsedFileUpdated);
this.initializing = true;
LoadSolutionProjects.AddJob(Initialize, "Loading " + project.Name + "...", GetInitializationWorkAmount());
}
void OnParsedFileUpdated(IParsedFile oldFile, IParsedFile newFile)
public void ParseInformationUpdated(IParsedFile oldFile, IParsedFile newFile)
{
// This method is called by the parser service within the parser service lock.
lock (lockObj) {
if (!disposed)
projectContent = projectContent.UpdateProjectContent(oldFile, newFile);
ParserService.InvalidateCurrentSolutionSnapshot();
SD.ParserService.InvalidateCurrentSolutionSnapshot();
}
}
@ -64,7 +62,7 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -64,7 +62,7 @@ namespace ICSharpCode.SharpDevelop.Parser
disposed = true;
}
foreach (var fileName in GetFilesToParse(project.Items)) {
ParserService.RemoveParsedFileListener(fileName, myListener);
SD.ParserService.RemoveOwnerProject(fileName.Item1, project);
}
initializing = false;
}
@ -107,12 +105,14 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -107,12 +105,14 @@ namespace ICSharpCode.SharpDevelop.Parser
initializing = false;
}
IEnumerable<FileName> GetFilesToParse(IEnumerable<ProjectItem> projectItems)
static readonly ItemType[] compilableItemTypes = { ItemType.Compile, ItemType.Page };
IEnumerable<Tuple<FileName, bool>> GetFilesToParse(IEnumerable<ProjectItem> projectItems)
{
return (
from p in projectItems
where (p.ItemType == ItemType.Compile || p.ItemType == ItemType.Page) && !String.IsNullOrEmpty(p.FileName)
select FileName.Create(p.FileName));
return
from p in projectItems.OfType<FileProjectItem>()
where compilableItemTypes.Contains(p.ItemType) && !String.IsNullOrEmpty(p.FileName)
select Tuple.Create(FileName.Create(p.FileName), p.IsLink);
}
void ParseFiles(ICollection<ProjectItem> projectItems, IProgressMonitor progressMonitor)
@ -128,16 +128,17 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -128,16 +128,17 @@ namespace ICSharpCode.SharpDevelop.Parser
MaxDegreeOfParallelism = Environment.ProcessorCount,
CancellationToken = progressMonitor.CancellationToken
},
fileName => {
tuple => {
var fileName = tuple.Item1;
// Don't read files we don't have a parser for.
// This avoids loading huge files (e.g. sdps) when we have no intention of parsing them.
if (ParserService.HasParser(fileName)) {
ParserService.AddParsedFileListener(fileName, myListener, startAsyncParse: false);
if (SD.ParserService.HasParser(fileName)) {
// We don't start an asynchronous parse operation since we want to
// parse on this thread.
SD.ParserService.AddOwnerProject(fileName, project, startAsyncParse: false, isLinkedFile: tuple.Item2);
ITextSource content = finder.Create(fileName);
if (content != null) {
// Parse the file on this thread so that AddParsedFileListener() does not
// start an asynchronous parse operation.
ParserService.ParseFile(fileName, content);
SD.ParserService.ParseFile(fileName, content, project);
}
}
lock (progressLock) {
@ -181,7 +182,7 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -181,7 +182,7 @@ namespace ICSharpCode.SharpDevelop.Parser
lock (lockObj) {
projectContent = projectContent.RemoveAssemblyReferences(this.references).AddAssemblyReferences(newReferences);
this.references = newReferences.ToArray();
ParserService.InvalidateCurrentSolutionSnapshot();
SD.ParserService.InvalidateCurrentSolutionSnapshot();
}
}, progressMonitor.CancellationToken);
}
@ -230,9 +231,10 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -230,9 +231,10 @@ namespace ICSharpCode.SharpDevelop.Parser
ReparseReferences();
}
}
if (e.ProjectItem.ItemType == ItemType.Compile) {
FileProjectItem fileProjectItem = e.ProjectItem as FileProjectItem;
if (fileProjectItem != null && compilableItemTypes.Contains(fileProjectItem.ItemType)) {
var fileName = FileName.Create(e.ProjectItem.FileName);
ParserService.AddParsedFileListener(fileName, myListener, startAsyncParse: true);
SD.ParserService.AddOwnerProject(fileName, project, startAsyncParse: true, isLinkedFile: fileProjectItem.IsLink);
}
}
@ -255,7 +257,7 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -255,7 +257,7 @@ namespace ICSharpCode.SharpDevelop.Parser
}
if (e.ProjectItem.ItemType == ItemType.Compile) {
ParserService.RemoveParsedFileListener(FileName.Create(e.ProjectItem.FileName), myListener);
SD.ParserService.RemoveOwnerProject(FileName.Create(e.ProjectItem.FileName), project);
}
}
}

18
src/Main/Base/Project/Src/Services/ParserService/ParsedFileListener.cs

@ -1,18 +0,0 @@ @@ -1,18 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.SharpDevelop.Parser
{
/// <summary>
/// Listener for parse info changes.
/// Caution: The callback is invoked within the parser service's lock. Beware of deadlocks!
/// The method is called on the thread that performed the parse operation, which might be the main thread
/// or a background thread.
/// If possible, use the <see cref="ParserService.ParseInformationUpdated"/> event instead, which is called on the main thread
/// and after the parser service released its lock.
/// </summary>
public delegate void ParsedFileListener(IParsedFile oldFile, IParsedFile newFile);
}

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

File diff suppressed because it is too large Load Diff

6
src/Main/Base/Project/Src/Services/ProjectService/ParseableFileContentFinder.cs

@ -17,7 +17,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -17,7 +17,7 @@ namespace ICSharpCode.SharpDevelop.Project
/// </summary>
public class ParseableFileContentFinder
{
FileName[] viewContentFileNamesCollection = WorkbenchSingleton.SafeThreadFunction(() => FileService.OpenedFiles.Select(f => f.FileName).ToArray());
FileName[] viewContentFileNamesCollection = SD.MainThread.InvokeIfRequired(() => FileService.OpenedFiles.Select(f => f.FileName).ToArray());
/// <summary>
/// Retrieves the file contents for the specified project items.
@ -26,10 +26,10 @@ namespace ICSharpCode.SharpDevelop.Project @@ -26,10 +26,10 @@ namespace ICSharpCode.SharpDevelop.Project
{
foreach (FileName name in viewContentFileNamesCollection) {
if (FileUtility.IsEqualFileName(name, fileName))
return WorkbenchSingleton.SafeThreadFunction(ParserService.GetParseableFileContent, fileName.ToString());
return SD.FileService.GetFileContent(fileName);
}
try {
return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(fileName, ParserService.DefaultFileEncoding));
return new StringTextSource(ICSharpCode.AvalonEdit.Utils.FileReader.ReadFileContent(fileName, SD.FileService.DefaultFileEncoding));
} catch (IOException) {
return null;
} catch (UnauthorizedAccessException) {

4
src/Main/Base/Project/Src/Services/ProjectService/ProjectService.cs

@ -300,8 +300,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -300,8 +300,7 @@ namespace ICSharpCode.SharpDevelop.Project
} catch (Exception ex) {
MessageService.ShowException(ex);
}
// Create project contents for solution
ParserService.OnSolutionLoaded();
SD.ParserService.InvalidateCurrentSolutionSnapshot();
Project.Converter.UpgradeViewContent.ShowIfRequired(openSolution);
@ -549,7 +548,6 @@ namespace ICSharpCode.SharpDevelop.Project @@ -549,7 +548,6 @@ namespace ICSharpCode.SharpDevelop.Project
openSolution.Dispose();
openSolution = null;
ParserService.OnSolutionClosed();
OnSolutionClosed(EventArgs.Empty);
CommandManager.InvalidateRequerySuggested();

35
src/Main/Base/Project/Src/Services/RefactoringService/FindReferenceService.cs

@ -67,7 +67,8 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -67,7 +67,8 @@ namespace ICSharpCode.SharpDevelop.Refactoring
throw new ArgumentNullException("progressMonitor");
if (callback == null)
throw new ArgumentNullException("callback");
if (ParserService.LoadSolutionProjectsThreadRunning) {
SD.MainThread.VerifyAccess();
if (SD.ParserService.LoadSolutionProjectsThreadRunning) {
progressMonitor.ShowingDialog = true;
MessageService.ShowMessage("${res:SharpDevelop.Refactoring.LoadSolutionProjectsThreadRunning}");
progressMonitor.ShowingDialog = false;
@ -90,26 +91,34 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -90,26 +91,34 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public static IObservable<SearchedFile> FindReferences(IEntity entity, IProgressMonitor progressMonitor)
{
return ReactiveExtensions.CreateObservable<SearchedFile>((monitor, callback) => FindReferencesAsync(entity, monitor, callback), progressMonitor);
return ReactiveExtensions.CreateObservable<SearchedFile>(
(monitor, callback) => FindReferencesAsync(entity, monitor, callback),
progressMonitor);
}
/// <summary>
/// Finds references to a local variable.
/// </summary>
public static void FindReferences(IVariable variable, Action<Reference> callback)
public static async Task<SearchedFile> FindLocalReferencesAsync(IVariable variable, IProgressMonitor progressMonitor)
{
if (variable == null)
throw new ArgumentNullException("variable");
if (callback == null)
throw new ArgumentNullException("callback");
if (progressMonitor == null)
throw new ArgumentNullException("progressMonitor");
var fileName = FileName.Create(variable.Region.FileName);
IParser parser = ParserService.GetParser(fileName);
var fileContent = ParserService.GetParseableFileContent(fileName);
ParseInformation pi = ParserService.Parse(fileName, fileContent);
if (pi == null || parser == null)
return;
var compilation = ParserService.GetCompilationForFile(fileName);
parser.FindLocalReferences(pi, fileContent, variable, compilation, callback, CancellationToken.None);
List<Reference> references = new List<Reference>();
await SD.ParserService.FindLocalReferencesAsync(
fileName, variable,
r => { lock (references) references.Add(r); },
cancellationToken: progressMonitor.CancellationToken);
return new SearchedFile(fileName, references);
}
public static IObservable<SearchedFile> FindLocalReferences(IVariable variable, IProgressMonitor progressMonitor)
{
return ReactiveExtensions.CreateObservable<SearchedFile>(
(monitor, callback) => FindLocalReferencesAsync(variable, monitor).ContinueWith(t => callback(t.Result)),
progressMonitor);
}
#endregion
@ -148,7 +157,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -148,7 +157,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
static SharpDevelopSolutionSnapshot GetSolutionSnapshot(ICompilation compilation)
{
var snapshot = compilation.SolutionSnapshot as SharpDevelopSolutionSnapshot;
return snapshot ?? ParserService.GetCurrentSolutionSnapshot();
return snapshot ?? SD.ParserService.GetCurrentSolutionSnapshot();
}

19
src/Main/Base/Project/Src/Services/RefactoringService/FindReferencesAndRenameHelper.cs

@ -234,6 +234,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -234,6 +234,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
*/
#region Common helper functions
[Obsolete]
public static ProvidedDocumentInformation GetDocumentInformation(string fileName)
{
OpenedFile file = FileService.GetOpenedFile(fileName);
@ -246,7 +247,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -246,7 +247,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
}
}
}
ITextSource fileContent = ParserService.GetParseableFileContent(fileName);
ITextSource fileContent = SD.FileService.GetFileContent(fileName);
return new ProvidedDocumentInformation(fileContent, fileName, 0);
}
@ -352,6 +353,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -352,6 +353,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
}
*/
[Obsolete]
public static void ShowAsSearchResults(string title, List<Reference> list)
{
if (list == null) return;
@ -361,7 +363,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -361,7 +363,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
IHighlighter highlighter = null;
foreach (Reference r in list) {
if (document == null || fileName != r.FileName) {
document = new TextDocument(ParserService.GetParseableFileContent(r.FileName));
document = new TextDocument(SD.FileService.GetFileContent(r.FileName));
fileName = r.FileName;
var def = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(r.FileName));
if (def != null)
@ -530,7 +532,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -530,7 +532,7 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public static void RunFindReferences(IEntity entity)
{
string entityName = (entity.DeclaringTypeDefinition != null ? entity.DeclaringTypeDefinition.Name + "." + entity.Name : entity.Name);
var monitor = WorkbenchSingleton.StatusBar.CreateProgressMonitor();
var monitor = SD.StatusBar.CreateProgressMonitor();
var results = FindReferenceService.FindReferences(entity, monitor);
SearchResultsPad.Instance.ShowSearchResults(StringParser.Parse("${res:SharpDevelop.Refactoring.ReferencesTo}", new StringTagPair("Name", entityName)), results);
SearchResultsPad.Instance.BringToFront();
@ -538,13 +540,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring @@ -538,13 +540,10 @@ namespace ICSharpCode.SharpDevelop.Refactoring
public static void RunFindReferences(LocalResolveResult local)
{
var references = new List<Reference>();
FindReferenceService.FindReferences(local.Variable, r => { lock (references) references.Add(r); });
FindReferencesAndRenameHelper.ShowAsSearchResults(
StringParser.Parse("${res:SharpDevelop.Refactoring.ReferencesTo}",
new StringTagPair("Name", local.Variable.Name)),
references
);
var monitor = SD.StatusBar.CreateProgressMonitor();
var results = FindReferenceService.FindLocalReferences(local.Variable, monitor);
SearchResultsPad.Instance.ShowSearchResults(StringParser.Parse("${res:SharpDevelop.Refactoring.ReferencesTo}", new StringTagPair("Name", local.Variable.Name)), results);
SearchResultsPad.Instance.BringToFront();
}
// public static ICSharpCode.Core.WinForms.MenuCommand MakeFindReferencesMenuCommand(EventHandler handler)

18
src/Main/Base/Project/Src/Services/SD.cs

@ -2,11 +2,13 @@ @@ -2,11 +2,13 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using ICSharpCode.Core;
using ICSharpCode.Core.Implementation;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
namespace ICSharpCode.SharpDevelop
{
@ -60,6 +62,10 @@ namespace ICSharpCode.SharpDevelop @@ -60,6 +62,10 @@ namespace ICSharpCode.SharpDevelop
get { return GetRequiredService<IWorkbench>(); }
}
public static IMessageLoop MainThread {
get { return GetRequiredService<IMessageLoop>(); }
}
/// <summary>
/// Gets the status bar.
/// </summary>
@ -82,5 +88,17 @@ namespace ICSharpCode.SharpDevelop @@ -82,5 +88,17 @@ namespace ICSharpCode.SharpDevelop
public static IAnalyticsMonitor AnalyticsMonitor {
get { return GetRequiredService<IAnalyticsMonitor>(); }
}
public static IParserService ParserService {
get { return GetRequiredService<IParserService>(); }
}
public static IFileService FileService {
get { return GetRequiredService<IFileService>(); }
}
public static IGlobalAssemblyCacheService GlobalAssemblyCache {
get { return GetRequiredService<IGlobalAssemblyCacheService>(); }
}
}
}

6
src/Main/Base/Project/Src/Services/Tasks/TaskService.cs

@ -77,15 +77,15 @@ namespace ICSharpCode.SharpDevelop @@ -77,15 +77,15 @@ namespace ICSharpCode.SharpDevelop
internal static void Initialize()
{
// avoid trouble with double initialization
ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated;
ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated;
SD.ParserService.ParseInformationUpdated -= ParserService_ParseInformationUpdated;
SD.ParserService.ParseInformationUpdated += ParserService_ParseInformationUpdated;
ProjectService.SolutionClosed -= ProjectServiceSolutionClosed;
ProjectService.SolutionClosed += ProjectServiceSolutionClosed;
}
static void ParserService_ParseInformationUpdated(object sender, ParseInformationEventArgs e)
{
if (e.NewParsedFile == ParserService.GetExistingParsedFile(e.FileName)) {
if (e.NewParsedFile == SD.ParserService.GetExistingParsedFile(e.FileName)) {
// Call UpdateCommentTags only for the main parse information (if a file is in multiple projects),
// and only if the results haven't already been replaced with a more recent ParseInformation.
if (e.NewParseInformation != null) {

2
src/Main/Base/Project/Src/Util/ExtensionMethods.cs

@ -583,7 +583,7 @@ namespace ICSharpCode.SharpDevelop @@ -583,7 +583,7 @@ namespace ICSharpCode.SharpDevelop
return newContent;
}
public static int IndexOfAny(this string haystack, string[] needles, int startIndex, out int matchLength)
public static int IndexOfAny(this string haystack, IEnumerable<string> needles, int startIndex, out int matchLength)
{
if (haystack == null)
throw new ArgumentNullException("haystack");

115
src/Main/Base/Project/Src/Util/MultiDictionary.cs

@ -0,0 +1,115 @@ @@ -0,0 +1,115 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// A dictionary that allows multiple pairs with the same key.
/// </summary>
public class MultiDictionary<TKey, TValue> : ILookup<TKey, TValue>
{
Dictionary<TKey, List<TValue>> dict;
public MultiDictionary()
{
}
public MultiDictionary(IEqualityComparer<TKey> comparer)
{
dict = new Dictionary<TKey, List<TValue>>(comparer);
}
public void Add(TKey key, TValue value)
{
List<TValue> valueList;
if (!dict.TryGetValue(key, out valueList)) {
valueList = new List<TValue>();
dict.Add(key, valueList);
}
valueList.Add(value);
}
public bool Remove(TKey key, TValue value)
{
List<TValue> valueList;
if (dict.TryGetValue(key, out valueList)) {
if (valueList.Remove(value)) {
if (valueList.Count == 0)
dict.Remove(key);
return true;
}
}
return false;
}
public void Clear()
{
dict.Clear();
}
public IReadOnlyList<TValue> this[TKey key] {
get {
List<TValue> list;
if (dict.TryGetValue(key, out list))
return list;
else
return new TValue[0];
}
}
public int Count {
get { return dict.Count; }
}
IEnumerable<TValue> ILookup<TKey, TValue>.this[TKey key] {
get { return this[key]; }
}
bool ILookup<TKey, TValue>.Contains(TKey key)
{
return dict.ContainsKey(key);
}
public IEnumerator<IGrouping<TKey, TValue>> GetEnumerator()
{
foreach (var pair in dict)
yield return new Grouping(pair.Key, pair.Value);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
sealed class Grouping : IGrouping<TKey, TValue>
{
readonly TKey key;
readonly List<TValue> values;
public Grouping(TKey key, List<TValue> values)
{
this.key = key;
this.values = values;
}
public TKey Key {
get { return key; }
}
public IEnumerator<TValue> GetEnumerator()
{
return values.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return values.GetEnumerator();
}
}
}
}

16
src/Main/Base/Project/Src/Util/ReactiveExtensions.cs

@ -3,10 +3,10 @@ @@ -3,10 +3,10 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop
@ -91,15 +91,17 @@ namespace ICSharpCode.SharpDevelop @@ -91,15 +91,17 @@ namespace ICSharpCode.SharpDevelop
return source.Subscribe(new AnonymousObserver<T>(onNext, onError, onCompleted));
}
public static List<T> ToList<T>(this IObservable<T> source, CancellationToken cancellation)
public static List<T> ToList<T>(this IObservable<T> source, CancellationToken cancellationToken)
{
List<T> results = new List<T>();
ManualResetEventSlim ev = new ManualResetEventSlim();
Exception error = null;
using (source.Subscribe(item => results.Add(item), exception => { error = exception; ev.Set(); }, () => ev.Set()))
ev.Wait(cancellation);
ExceptionDispatchInfo error = null;
using (source.Subscribe(item => results.Add(item),
exception => { error = ExceptionDispatchInfo.Capture(exception); ev.Set(); },
() => ev.Set()))
ev.Wait(cancellationToken);
if (error != null)
throw new TargetInvocationException(error);
error.Throw();
return results;
}

112
src/Main/Base/Project/Src/Util/WorkerThread.cs

@ -1,112 +0,0 @@ @@ -1,112 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Threading;
namespace ICSharpCode.SharpDevelop.Util
{
/// <summary>
/// A worker thread that normally sleeps, but can run a queue of commands.
///
/// This class does not create a worker thread on its own, it merely manages tasks for
/// the worker thread that calls <see cref="RunLoop"/>.
/// </summary>
public class WorkerThread
{
sealed class AsyncTask : IAsyncResult
{
internal readonly ManualResetEventSlim manualResetEvent = new ManualResetEventSlim(false);
internal readonly Action method;
volatile bool isCompleted;
internal AsyncTask(Action method)
{
this.method = method;
}
internal void SetCompleted()
{
isCompleted = true;
manualResetEvent.Set();
}
public bool IsCompleted {
get { return isCompleted; }
}
public WaitHandle AsyncWaitHandle {
get { return manualResetEvent.WaitHandle; }
}
public object AsyncState { get; set; }
public bool CompletedSynchronously { get { return false; } }
}
/// <summary>
/// Runs <paramref name="method"/> on the worker thread.
/// </summary>
/// <param name="method">The method to run.</param>
/// <returns>IAsyncResult that gets completed when the action has executed.</returns>
public IAsyncResult Enqueue(Action method)
{
if (method == null)
throw new ArgumentNullException("method");
AsyncTask task = new AsyncTask(method);
lock (lockObject) {
taskQueue.Enqueue(task);
Monitor.Pulse(lockObject);
}
return task;
}
readonly object lockObject = new object();
// access needs lock using 'lockObject'
Queue<AsyncTask> taskQueue = new Queue<AsyncTask>();
// access needs lock using 'lockObject'
bool workerRunning;
// not a shared variable: accessed only within worker thread
bool exitWorker;
/// <summary>
/// Runs the worker thread loop on the current thread.
/// </summary>
public void RunLoop()
{
lock (lockObject) {
if (workerRunning)
throw new InvalidOperationException("There already is a worker running");
workerRunning = true;
}
try {
exitWorker = false;
while (!exitWorker) {
AsyncTask task;
lock (lockObject) {
while (taskQueue.Count == 0)
Monitor.Wait(lockObject);
task = taskQueue.Dequeue();
}
task.method();
task.SetCompleted();
}
} finally {
lock (lockObject) {
workerRunning = false;
}
}
}
/// <summary>
/// Exits running the worker thread after executing all currently enqueued methods.
/// </summary>
/// <returns>IAsyncResult that gets completed when the worker thread has shut down.</returns>
public IAsyncResult ExitWorkerThread()
{
return Enqueue(delegate { exitWorker = true; });
}
}
}

120
src/Main/Base/Project/Src/Util/WpfSynchronizeInvoke.cs

@ -1,120 +0,0 @@ @@ -1,120 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Reflection;
using System.Threading;
using System.Windows.Threading;
namespace ICSharpCode.SharpDevelop
{
/// <summary>
/// Implements the ISynchronizeInvoke interface by using a WPF dispatcher
/// to perform the cross-thread call.
/// </summary>
sealed class WpfSynchronizeInvoke : ISynchronizeInvoke
{
readonly Dispatcher dispatcher;
public WpfSynchronizeInvoke(Dispatcher dispatcher)
{
if (dispatcher == null)
throw new ArgumentNullException("dispatcher");
this.dispatcher = dispatcher;
}
public bool InvokeRequired {
get {
return !dispatcher.CheckAccess();
}
}
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
DispatcherOperation op;
if (args == null || args.Length == 0)
op = dispatcher.BeginInvoke(DispatcherPriority.Normal, method);
else if (args.Length == 1)
op = dispatcher.BeginInvoke(DispatcherPriority.Normal, method, args[0]);
else
op = dispatcher.BeginInvoke(DispatcherPriority.Normal, method, args[0], args.Splice(1));
return new AsyncResult(op);
}
sealed class AsyncResult : IAsyncResult
{
internal readonly DispatcherOperation op;
readonly object lockObj = new object();
ManualResetEvent resetEvent;
public AsyncResult(DispatcherOperation op)
{
this.op = op;
}
public bool IsCompleted {
get {
return op.Status == DispatcherOperationStatus.Completed;
}
}
public WaitHandle AsyncWaitHandle {
get {
lock (lockObj) {
if (resetEvent == null) {
op.Completed += op_Completed;
resetEvent = new ManualResetEvent(false);
if (IsCompleted)
resetEvent.Set();
}
return resetEvent;
}
}
}
void op_Completed(object sender, EventArgs e)
{
lock (lockObj) {
resetEvent.Set();
}
}
public object AsyncState {
get { return null; }
}
public bool CompletedSynchronously {
get { return false; }
}
}
public object EndInvoke(IAsyncResult result)
{
AsyncResult r = result as AsyncResult;
if (r == null)
throw new ArgumentException("result must be the return value of a WpfSynchronizeInvoke.BeginInvoke call!");
r.op.Wait();
return r.op.Result;
}
public object Invoke(Delegate method, object[] args)
{
object result = null;
Exception exception = null;
dispatcher.Invoke(
DispatcherPriority.Normal,
(Action)delegate {
try {
result = method.DynamicInvoke(args);
} catch (TargetInvocationException ex) {
exception = ex.InnerException;
}
});
// if an exception occurred, re-throw it on the calling thread
if (exception != null)
throw new TargetInvocationException(exception);
return result;
}
}
}

0
src/Main/Base/Project/Src/Services/ParserService/Fusion.cs → src/Main/SharpDevelop/Parser/Fusion.cs

28
src/Main/Base/Project/Src/Services/ParserService/GacInterop.cs → src/Main/SharpDevelop/Parser/GlobalAssemblyCacheService.cs

@ -1,25 +1,21 @@ @@ -1,25 +1,21 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
// Based on the MIT-licensed GacInterop.cs from ILSpy.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Mono.Cecil;
namespace ICSharpCode.SharpDevelop.Parser
{
/// <summary>
/// Interop with the .NET GAC.
/// </summary>
public static class GacInterop
sealed class GlobalAssemblyCacheService : IGlobalAssemblyCacheService
{
/// <summary>
/// Gets the names of all assemblies in the GAC.
/// </summary>
public static IEnumerable<DomAssemblyName> GetGacAssemblyFullNames()
public bool IsGACAssembly(string fileName)
{
throw new NotImplementedException();
}
public IEnumerable<DomAssemblyName> GetGacAssemblyFullNames()
{
IApplicationContext applicationContext = null;
IAssemblyEnum assemblyEnum = null;
@ -37,7 +33,7 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -37,7 +33,7 @@ namespace ICSharpCode.SharpDevelop.Parser
}
}
#region FindAssemblyInGac
#region FindAssemblyInNetGac
// This region is based on code from Mono.Cecil:
// Author:
@ -65,14 +61,14 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -65,14 +61,14 @@ namespace ICSharpCode.SharpDevelop.Parser
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
static readonly string[] gac_paths = { Fusion.GetGacPath(false), Fusion.GetGacPath(true) };
static readonly string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" };
static readonly string[] prefixes = { string.Empty, "v4.0_" };
readonly string[] gac_paths = { Fusion.GetGacPath(false), Fusion.GetGacPath(true) };
readonly string[] gacs = { "GAC_MSIL", "GAC_32", "GAC" };
readonly string[] prefixes = { string.Empty, "v4.0_" };
/// <summary>
/// Gets the file name for an assembly stored in the GAC.
/// </summary>
public static string FindAssemblyInNetGac (DomAssemblyName reference)
public string FindAssemblyInNetGac (DomAssemblyName reference)
{
// without public key, it can't be in the GAC
if (reference.PublicKeyToken == null)

2
src/Main/Base/Project/Src/Services/ParserService/Doozer/ParserDescriptor.cs → src/Main/SharpDevelop/Parser/ParserDescriptor.cs

@ -8,7 +8,7 @@ using ICSharpCode.SharpDevelop.Project; @@ -8,7 +8,7 @@ using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Parser
{
public sealed class ParserDescriptor
sealed class ParserDescriptor
{
Codon codon;
Type parserType;

2
src/Main/Base/Project/Src/Services/ParserService/Doozer/ParserDoozer.cs → src/Main/SharpDevelop/Parser/ParserDoozer.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.SharpDevelop.Parser @@ -20,7 +20,7 @@ namespace ICSharpCode.SharpDevelop.Parser
/// <returns>
/// An ParserDescriptor object that wraps the IParser object.
/// </returns>
public sealed class ParserDoozer : IDoozer
sealed class ParserDoozer : IDoozer
{
/// <summary>
/// Gets if the doozer handles codon conditions on its own.

359
src/Main/SharpDevelop/Parser/ParserService.cs

@ -0,0 +1,359 @@ @@ -0,0 +1,359 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
using ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Refactoring;
namespace ICSharpCode.SharpDevelop.Parser
{
sealed class ParserService : IParserService
{
IList<ParserDescriptor> parserDescriptors;
public ParserService()
{
parserDescriptors = AddInTree.BuildItems<ParserDescriptor>("/Workspace/Parser", null, false);
}
#region ParseInformationUpdated
public event EventHandler<ParseInformationEventArgs> ParseInformationUpdated = delegate {};
internal void RaiseParseInformationUpdated(ParseInformationEventArgs e)
{
// RaiseParseInformationUpdated is called inside a lock, but we don't want to raise the event inside that lock.
// To ensure events are raised in the same order, we always invoke on the main thread.
WorkbenchSingleton.SafeThreadAsyncCall(
delegate {
string addition;
if (e.OldParsedFile == null)
addition = " (new)";
else if (e.NewParsedFile == null)
addition = " (removed)";
else
addition = " (updated)";
LoggingService.Debug("ParseInformationUpdated " + e.FileName + addition);
ParseInformationUpdated(null, e);
});
}
#endregion
#region TaskListTokens
IReadOnlyList<string> taskListTokens = LoadTaskListTokens();
public IReadOnlyList<string> TaskListTokens {
get { return taskListTokens; }
set {
SD.MainThread.VerifyAccess();
if (!value.SequenceEqual(taskListTokens)) {
taskListTokens = value.ToArray();
PropertyService.SetList("SharpDevelop.TaskListTokens", taskListTokens);
// TODO: trigger reparse?
}
}
}
static IReadOnlyList<string> LoadTaskListTokens()
{
if (PropertyService.Contains("SharpDevelop.TaskListTokens"))
return PropertyService.GetList<string>("SharpDevelop.TaskListTokens").ToArray();
else
return new string[] { "HACK", "TODO", "UNDONE", "FIXME" };
}
#endregion
#region Load Solution Projects Thread
public bool LoadSolutionProjectsThreadRunning {
get { return false; }
}
public event EventHandler LoadSolutionProjectsThreadStarted;
public event EventHandler LoadSolutionProjectsThreadEnded;
#endregion
#region Compilation
public ICompilation GetCompilation(IProject project)
{
return GetCurrentSolutionSnapshot().GetCompilation(project);
}
public ICompilation GetCompilationForFile(FileName fileName)
{
Solution solution = ProjectService.OpenSolution;
IProject project = solution != null ? solution.FindProjectContainingFile(fileName) : null;
if (project != null)
return GetCompilation(project);
var entry = GetFileEntry(fileName, false);
if (entry != null && entry.parser != null) {
var parsedFile = entry.GetExistingParsedFile(null, null);
if (parsedFile != null) {
ICompilation compilation = entry.parser.CreateCompilationForSingleFile(fileName, parsedFile);
if (compilation != null)
return compilation;
}
}
return MinimalCorlib.Instance.CreateCompilation();
}
// Use a WeakReference for caching the solution snapshot - it can require
// lots of memory and may not be invalidated soon enough if the user
// is only browsing code.
volatile WeakReference<SharpDevelopSolutionSnapshot> currentSolutionSnapshot;
public SharpDevelopSolutionSnapshot GetCurrentSolutionSnapshot()
{
var weakRef = currentSolutionSnapshot;
SharpDevelopSolutionSnapshot result;
if (weakRef == null || !weakRef.TryGetTarget(out result)) {
// create new snapshot if we don't have one cached
result = new SharpDevelopSolutionSnapshot(ProjectService.OpenSolution);
currentSolutionSnapshot = new WeakReference<SharpDevelopSolutionSnapshot>(result);
}
return result;
}
public void InvalidateCurrentSolutionSnapshot()
{
currentSolutionSnapshot = null;
}
#endregion
#region Entry management
const int cachedEntryCount = 5;
Dictionary<FileName, ParserServiceEntry> fileEntryDict = new Dictionary<FileName, ParserServiceEntry>();
Queue<ParserServiceEntry> cacheExpiryQueue = new Queue<ParserServiceEntry>();
ParserServiceEntry GetFileEntry(FileName fileName, bool createIfMissing)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
ParserServiceEntry entry;
lock (fileEntryDict) {
if (!fileEntryDict.TryGetValue(fileName, out entry)) {
if (!createIfMissing)
return null;
entry = new ParserServiceEntry(this, fileName);
fileEntryDict.Add(fileName, entry);
}
}
return entry;
}
public void ClearParseInformation(FileName fileName)
{
ParserServiceEntry entry = GetFileEntry(fileName, false);
if (entry != null) {
entry.ExpireCache();
}
}
internal void RemoveEntry(ParserServiceEntry entry)
{
Debug.Assert(Monitor.IsEntered(entry));
lock (fileEntryDict) {
ParserServiceEntry entryAtKey;
if (fileEntryDict.TryGetValue(entry.fileName, out entryAtKey)) {
if (entry == entryAtKey)
fileEntryDict.Remove(entry.fileName);
}
}
}
internal void RegisterForCacheExpiry(ParserServiceEntry entry)
{
// This method should not be called within any locks
Debug.Assert(!Monitor.IsEntered(entry));
ParserServiceEntry expiredItem = null;
lock (cacheExpiryQueue) {
if (cacheExpiryQueue.Count >= cachedEntryCount) {
expiredItem = cacheExpiryQueue.Dequeue();
}
cacheExpiryQueue.Enqueue(entry);
}
if (expiredItem != null)
expiredItem.ExpireCache();
}
public void AddOwnerProject(FileName fileName, IProject project, bool startAsyncParse, bool isLinkedFile)
{
if (project == null)
throw new ArgumentNullException("project");
GetFileEntry(fileName, true).AddOwnerProject(project, isLinkedFile);
}
public void RemoveOwnerProject(FileName fileName, IProject project)
{
if (project == null)
throw new ArgumentNullException("project");
var entry = GetFileEntry(fileName, false);
if (entry != null)
entry.RemoveOwnerProject(project);
}
#endregion
#region Forward Parse() calls to entry
public IParsedFile GetExistingParsedFile(FileName fileName, ITextSourceVersion version, IProject parentProject)
{
var entry = GetFileEntry(fileName, false);
if (entry != null)
return entry.GetExistingParsedFile(version, parentProject);
else
return null;
}
public ParseInformation GetCachedParseInformation(FileName fileName, ITextSourceVersion version, IProject parentProject)
{
var entry = GetFileEntry(fileName, false);
if (entry != null)
return entry.GetCachedParseInformation(version, parentProject);
else
return null;
}
public ParseInformation Parse(FileName fileName, ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return GetFileEntry(fileName, true).Parse(fileContent, parentProject, cancellationToken);
}
public IParsedFile ParseFile(FileName fileName, ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return GetFileEntry(fileName, true).ParseFile(fileContent, parentProject, cancellationToken);
}
public Task<ParseInformation> ParseAsync(FileName fileName, ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return GetFileEntry(fileName, true).ParseAsync(fileContent, parentProject, cancellationToken);
}
public Task<IParsedFile> ParseFileAsync(FileName fileName, ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return GetFileEntry(fileName, true).ParseFileAsync(fileContent, parentProject, cancellationToken);
}
#endregion
#region Resolve
public ResolveResult Resolve(ITextEditor editor, TextLocation location, ICompilation compilation, CancellationToken cancellationToken)
{
if (editor == null)
throw new ArgumentNullException("editor");
return Resolve(editor.FileName, location, editor.Document, compilation, cancellationToken);
}
public ResolveResult Resolve(FileName fileName, TextLocation location, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken)
{
var entry = GetFileEntry(fileName, true);
if (entry.parser == null)
return ErrorResolveResult.UnknownError;
IProject project = compilation != null ? compilation.GetProject() : null;
var parseInfo = entry.Parse(fileContent, project, cancellationToken);
if (parseInfo == null)
return ErrorResolveResult.UnknownError;
if (compilation == null)
compilation = GetCompilationForFile(fileName);
ResolveResult rr = entry.parser.Resolve(parseInfo, location, compilation, cancellationToken);
LoggingService.Debug("Resolved " + location + " to " + rr);
return rr;
}
public Task<ResolveResult> ResolveAsync(FileName fileName, TextLocation location, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken)
{
var entry = GetFileEntry(fileName, true);
if (entry.parser == null)
return Task.FromResult<ResolveResult>(ErrorResolveResult.UnknownError);
IProject project = compilation != null ? compilation.GetProject() : null;
return entry.ParseAsync(fileContent, project, cancellationToken).ContinueWith(
delegate (Task<ParseInformation> parseInfoTask) {
var parseInfo = parseInfoTask.Result;
if (parseInfo == null)
return ErrorResolveResult.UnknownError;
if (compilation == null)
compilation = GetCompilationForFile(fileName);
ResolveResult rr = entry.parser.Resolve(parseInfo, location, compilation, cancellationToken);
LoggingService.Debug("Resolved " + location + " to " + rr);
return rr;
}, cancellationToken);
}
public async Task FindLocalReferencesAsync(FileName fileName, IVariable variable, Action<Reference> callback, ITextSource fileContent, ICompilation compilation, CancellationToken cancellationToken)
{
var entry = GetFileEntry(fileName, true);
if (entry.parser == null)
return;
if (fileContent == null)
fileContent = SD.FileService.GetFileContent(fileName);
if (compilation == null)
compilation = GetCompilationForFile(fileName);
var parseInfo = await entry.ParseAsync(fileContent, compilation.GetProject(), cancellationToken).ConfigureAwait(false);
await Task.Run(
() => entry.parser.FindLocalReferences(parseInfo, fileContent, variable, compilation, callback, cancellationToken)
);
}
#endregion
#region HasParser / CreateParser
public bool HasParser(FileName fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (parserDescriptors == null)
return false;
foreach (ParserDescriptor descriptor in parserDescriptors) {
if (descriptor.CanParse(fileName)) {
return true;
}
}
return false;
}
/// <summary>
/// Creates a new IParser instance that can parse the specified file.
/// This method is thread-safe.
/// </summary>
internal IParser CreateParser(FileName fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (parserDescriptors == null)
return null;
foreach (ParserDescriptor descriptor in parserDescriptors) {
if (descriptor.CanParse(fileName)) {
IParser p = descriptor.CreateParser();
if (p != null) {
p.TaskListTokens = TaskListTokens;
return p;
}
}
}
return null;
}
#endregion
internal void StartParserThread()
{
// TODO
}
internal void StopParserThread()
{
// TODO
}
}
}

330
src/Main/SharpDevelop/Parser/ParserServiceEntry.cs

@ -0,0 +1,330 @@ @@ -0,0 +1,330 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Parser
{
sealed class ParserServiceEntry
{
struct ProjectEntry
{
public readonly IProject Project;
public readonly IParsedFile ParsedFile;
public readonly ParseInformation CachedParseInformation;
public ProjectEntry(IProject project, IParsedFile parsedFile, ParseInformation cachedParseInformation)
{
this.Project = project;
this.ParsedFile = parsedFile;
this.CachedParseInformation = cachedParseInformation;
}
}
readonly ParserService parserService;
internal readonly FileName fileName;
internal readonly IParser parser;
List<ProjectEntry> entries = new List<ProjectEntry> { default(ProjectEntry) };
ITextSourceVersion currentVersion;
public ParserServiceEntry(ParserService parserService, FileName fileName)
{
this.parserService = parserService;
this.fileName = fileName;
this.parser = parserService.CreateParser(fileName);
}
#region Owner Projects
IProject PrimaryProject {
get { return entries[0].Project; }
}
int FindIndexForProject(IProject parentProject)
{
if (parentProject == null)
return 0;
for (int i = 0; i < entries.Count; i++) {
if (entries[i].Project == parentProject)
return i;
}
// project not found
return -1;
}
public void AddOwnerProject(IProject project, bool isLinkedFile)
{
Debug.Assert(project != null);
lock (this) {
if (FindIndexForProject(project) >= 0)
throw new InvalidOperationException("The project alreadys owns the file");
ProjectEntry newEntry = new ProjectEntry(project, null, null);
if (entries[0].Project == null) {
entries[0] = newEntry;
} else if (isLinkedFile) {
entries.Add(newEntry);
} else {
entries.Insert(0, newEntry);
}
}
}
public void RemoveOwnerProject(IProject project)
{
Debug.Assert(project != null);
lock (this) {
int index = FindIndexForProject(project);
if (index < 0)
throw new InvalidOperationException("The project does not own the file");
if (entries.Count == 1) {
entries[0] = default(ProjectEntry);
} else {
entries.RemoveAt(index);
}
}
}
#endregion
/// <summary>
/// Compares currentVersion with version.
/// -1 = currentVersion is older; 0 = same version; 1 = newVersion is older
/// </summary>
int CompareVersions(ITextSourceVersion newVersion)
{
if (currentVersion != null && newVersion != null && currentVersion.BelongsToSameDocumentAs(newVersion))
return currentVersion.CompareAge(newVersion);
else
return -1;
}
#region Expire Cache + GetExistingParsedFile + GetCachedParseInformation
public void ExpireCache()
{
lock (this) {
if (PrimaryProject == null) {
parserService.RemoveEntry(this);
} else {
for (int i = 0; i < entries.Count; i++) {
var oldEntry = entries[i];
entries[i] = new ProjectEntry(oldEntry.Project, oldEntry.ParsedFile, null);
}
}
}
}
public IParsedFile GetExistingParsedFile(ITextSourceVersion version, IProject parentProject)
{
lock (this) {
if (version != null && CompareVersions(version) != 0) {
return null;
}
int index = FindIndexForProject(parentProject);
if (index < 0)
return null;
return entries[index].ParsedFile;
}
}
public ParseInformation GetCachedParseInformation(ITextSourceVersion version, IProject parentProject)
{
lock (this) {
if (version != null && CompareVersions(version) != 0) {
return null;
}
int index = FindIndexForProject(parentProject);
if (index < 0)
return null;
return entries[index].CachedParseInformation;
}
}
#endregion
#region Parse
public ParseInformation Parse(ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
if (fileContent == null) {
fileContent = SD.FileService.GetFileContent(fileName);
}
return DoParse(fileContent, parentProject, false, cancellationToken).CachedParseInformation;
}
public IParsedFile ParseFile(ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
if (fileContent == null) {
fileContent = SD.FileService.GetFileContent(fileName);
}
return DoParse(fileContent, parentProject, false, cancellationToken).ParsedFile;
}
ProjectEntry DoParse(ITextSource fileContent, IProject parentProject, bool fullParseInformationRequested,
CancellationToken cancellationToken)
{
if (parser == null)
return default(ProjectEntry);
if (fileContent == null) {
// No file content was specified. Because the callers of this method already check for currently open files,
// we can assume that the file isn't open and simply read it from disk.
try {
fileContent = SD.FileService.GetFileContentFromDisk(fileName, cancellationToken);
} catch (IOException) {
// It is possible that the file gets deleted/becomes inaccessible while a background parse
// operation is enqueued, so we have to handle IO exceptions.
return default(ProjectEntry);
} catch (UnauthorizedAccessException) {
return default(ProjectEntry);
}
}
ProjectEntry result;
lock (this) {
int index = FindIndexForProject(parentProject);
int versionComparison = CompareVersions(fileContent.Version);
if (versionComparison > 0 || index < 0) {
// We're going backwards in time, or are requesting a project that is not an owner
// for this entry.
var parseInfo = parser.Parse(fileName, fileContent, fullParseInformationRequested, parentProject, cancellationToken);
FreezableHelper.Freeze(parseInfo.ParsedFile);
return new ProjectEntry(parentProject, parseInfo.ParsedFile, parseInfo);
} else {
if (versionComparison == 0 && index >= 0) {
// If full parse info is requested, ensure we have full parse info.
if (!(fullParseInformationRequested && entries[index].CachedParseInformation == null)) {
// We already have the requested version parsed, just return it:
return entries[index];
}
}
}
ParseInformationEventArgs[] results = new ParseInformationEventArgs[entries.Count];
for (int i = 0; i < entries.Count; i++) {
ParseInformation parseInfo;
try {
parseInfo = parser.Parse(fileName, fileContent, fullParseInformationRequested, entries[i].Project, cancellationToken);
} catch (Exception ex) {
SD.LoggingService.Error("Got " + ex.GetType().Name + " while parsing " + fileName);
throw;
}
if (parseInfo == null)
throw new NullReferenceException(parser.GetType().Name + ".Parse() returned null");
if (fullParseInformationRequested && !parseInfo.IsFullParseInformation)
throw new InvalidOperationException(parser.GetType().Name + ".Parse() did not return full parse info as requested.");
FreezableHelper.Freeze(parseInfo.ParsedFile);
results[i] = new ParseInformationEventArgs(entries[i].Project, entries[i].ParsedFile, parseInfo);
}
// Only if all parse runs succeeded, register the parse information.
currentVersion = fileContent.Version;
for (int i = 0; i < entries.Count; i++) {
if (fullParseInformationRequested || entries[i].CachedParseInformation != null)
entries[i] = new ProjectEntry(entries[i].Project, entries[i].ParsedFile, results[i].NewParseInformation);
else
entries[i] = new ProjectEntry(entries[i].Project, entries[i].ParsedFile, null);
if (entries[i].Project != null)
entries[i].Project.OnParseInformationUpdated(results[i]);
parserService.RaiseParseInformationUpdated(results[i]);
}
result = entries[index];
} // exit lock
parserService.RegisterForCacheExpiry(this);
return result;
}
#endregion
#region ParseAsync
Task<ProjectEntry> runningAsyncParseTask;
ITextSourceVersion runningAsyncParseFileContentVersion;
bool runningAsyncParseFullInfoRequested;
public async Task<ParseInformation> ParseAsync(ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return (await DoParseAsync(fileContent, parentProject, true, cancellationToken)).CachedParseInformation;
}
public async Task<IParsedFile> ParseFileAsync(ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken)
{
return (await DoParseAsync(fileContent, parentProject, false, cancellationToken)).ParsedFile;
}
Task<ProjectEntry> DoParseAsync(ITextSource fileContent, IProject parentProject, bool requestFullParseInformation, CancellationToken cancellationToken)
{
// Create snapshot of file content, if required
bool lookupOpenFileOnTargetThread;
if (fileContent != null) {
lookupOpenFileOnTargetThread = false;
// File content was explicitly specified:
// Let's make a snapshot in case the text source is mutable.
fileContent = fileContent.CreateSnapshot();
} else if (SD.MainThread.InvokeRequired) {
// fileContent == null && not on the main thread:
// Don't fetch the file content right now; if we need to SafeThreadCall() anyways,
// it's better to do so from the background task.
lookupOpenFileOnTargetThread = true;
} else {
// fileContent == null && we are on the main thread:
// Let's look up the file in the list of open files right now
// so that we don't need to SafeThreadCall() later on.
lookupOpenFileOnTargetThread = false;
fileContent = SD.FileService.GetFileContentForOpenFile(fileName);
}
Task<ProjectEntry> task;
lock (this) {
if (fileContent != null) {
// Optimization:
// don't start a background task if fileContent was specified and up-to-date parse info is available
int index = FindIndexForProject(parentProject);
int versionComparison = CompareVersions(fileContent.Version);
if (versionComparison == 0 && index >= 0) {
// If full parse info is requested, ensure we have full parse info.
if (!(requestFullParseInformation && entries[index].CachedParseInformation == null)) {
// We already have the requested version parsed, just return it:
return Task.FromResult(entries[index]);
}
}
// Optimization:
// if an equivalent task is already running, return that one instead
if (runningAsyncParseTask != null && (!requestFullParseInformation || runningAsyncParseFullInfoRequested)
&& runningAsyncParseFileContentVersion.BelongsToSameDocumentAs(fileContent.Version)
&& runningAsyncParseFileContentVersion.CompareAge(fileContent.Version) == 0)
{
return runningAsyncParseTask;
}
}
task = new Task<ProjectEntry>(
delegate {
try {
if (lookupOpenFileOnTargetThread) {
fileContent = SD.FileService.GetFileContentForOpenFile(fileName);
}
return DoParse(fileContent, parentProject, requestFullParseInformation, cancellationToken);
} finally {
lock (this) {
runningAsyncParseTask = null;
runningAsyncParseFileContentVersion = null;
}
}
}, cancellationToken);
if (fileContent != null && fileContent.Version != null && !cancellationToken.CanBeCanceled) {
runningAsyncParseTask = task;
runningAsyncParseFileContentVersion = fileContent.Version;
runningAsyncParseFullInfoRequested = requestFullParseInformation;
}
}
task.Start();
return task;
}
#endregion
}
}

2
src/Main/SharpDevelop/Sda/CallHelper.cs

@ -17,7 +17,7 @@ using ICSharpCode.Core; @@ -17,7 +17,7 @@ using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop.Commands;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.Workbench;
using ICSharpCode.SharpDevelop.Workbench;
using ICSharpCode.SharpDevelop.Logging;
using ICSharpCode.SharpDevelop.Parser;

45
src/Main/SharpDevelop/SharpDevelop.csproj

@ -77,23 +77,32 @@ @@ -77,23 +77,32 @@
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Gui\App.xaml.cs" />
<Compile Include="Gui\SplashScreen.cs" />
<Compile Include="Gui\Workbench\AvalonDockLayout.cs" />
<Compile Include="Gui\Workbench\AvalonPadContent.cs" />
<Compile Include="Gui\Workbench\AvalonWorkbenchWindow.cs" />
<Compile Include="Gui\Workbench\ChooseLayoutCommand.cs" />
<Compile Include="Gui\Workbench\FullScreenEnabledWindow.cs" />
<Compile Include="Gui\Workbench\LayoutConfiguration.cs" />
<Compile Include="Gui\Workbench\SDStatusBar.cs" />
<Compile Include="Gui\Workbench\SingleInstanceHelper.cs" />
<Compile Include="Gui\Workbench\StatusBarService.cs" />
<Compile Include="Gui\Workbench\WorkbenchStartup.cs" />
<Compile Include="Gui\Workbench\WpfWorkbench.cs" />
<Compile Include="Startup\App.xaml.cs" />
<Compile Include="Startup\SharpDevelopMain.cs" />
<Compile Include="Startup\SplashScreen.cs" />
<Compile Include="Workbench\AvalonDockLayout.cs" />
<Compile Include="Workbench\AvalonPadContent.cs" />
<Compile Include="Workbench\AvalonWorkbenchWindow.cs" />
<Compile Include="Workbench\ChooseLayoutCommand.cs" />
<Compile Include="Workbench\DispatcherMessageLoop.cs" />
<Compile Include="Workbench\FileService.cs" />
<Compile Include="Workbench\FullScreenEnabledWindow.cs" />
<Compile Include="Workbench\LayoutConfiguration.cs" />
<Compile Include="Workbench\SDStatusBar.cs" />
<Compile Include="Workbench\SingleInstanceHelper.cs" />
<Compile Include="Workbench\StatusBarService.cs" />
<Compile Include="Workbench\WorkbenchStartup.cs" />
<Compile Include="Workbench\WpfWorkbench.cs" />
<Compile Include="Logging\ExceptionBox.cs" />
<Compile Include="Logging\log4netLoggingService.cs" />
<Compile Include="Logging\LogMessageRecorder.cs" />
<Compile Include="Logging\SDMessageService.cs" />
<Compile Include="Parser\Fusion.cs" />
<Compile Include="Parser\GlobalAssemblyCacheService.cs" />
<Compile Include="Parser\ParserDescriptor.cs" />
<Compile Include="Parser\ParserDoozer.cs" />
<Compile Include="Parser\ParserService.cs" />
<Compile Include="Parser\ParserServiceEntry.cs" />
<Compile Include="Sda\CallHelper.cs" />
<Compile Include="Sda\Document.cs" />
<Compile Include="Sda\EventArgs.cs" />
@ -101,7 +110,6 @@ @@ -101,7 +110,6 @@
<Compile Include="Sda\SharpDevelopHost.cs" />
<Compile Include="Sda\StartupSettings.cs" />
<Compile Include="Sda\WorkbenchSettings.cs" />
<Compile Include="SharpDevelopMain.cs" />
<EmbeddedResource Include="..\..\..\data\resources\StringResources.resx">
<Link>Resources\StringResources.resx</Link>
</EmbeddedResource>
@ -174,14 +182,15 @@ @@ -174,14 +182,15 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Gui" />
<Folder Include="Gui\Workbench" />
<Folder Include="Startup" />
<Folder Include="Workbench" />
<Folder Include="Logging" />
<Folder Include="Parser" />
<Folder Include="Sda" />
</ItemGroup>
<ItemGroup>
<Page Include="Gui\App.xaml" />
<Page Include="Gui\Workbench\WpfWorkbench.xaml" />
<Page Include="Startup\App.xaml" />
<Page Include="Workbench\WpfWorkbench.xaml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

2
src/Main/SharpDevelop/Gui/App.xaml → src/Main/SharpDevelop/Startup/App.xaml

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
<Application x:Class="ICSharpCode.SharpDevelop.Gui.App" x:ClassModifier="internal"
<Application x:Class="ICSharpCode.SharpDevelop.Startup.App" x:ClassModifier="internal"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:core = "http://icsharpcode.net/sharpdevelop/core"

2
src/Main/SharpDevelop/Gui/App.xaml.cs → src/Main/SharpDevelop/Startup/App.xaml.cs

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
using System;
using System.Windows;
namespace ICSharpCode.SharpDevelop.Gui
namespace ICSharpCode.SharpDevelop.Startup
{
/// <summary>
/// Interaction logic for App.xaml

4
src/Main/SharpDevelop/SharpDevelopMain.cs → src/Main/SharpDevelop/Startup/SharpDevelopMain.cs

@ -10,12 +10,12 @@ using System.Windows.Forms; @@ -10,12 +10,12 @@ using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.Workbench;
using ICSharpCode.SharpDevelop.Workbench;
using ICSharpCode.SharpDevelop.Logging;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Sda;
namespace ICSharpCode.SharpDevelop
namespace ICSharpCode.SharpDevelop.Startup
{
/// <summary>
/// This Class is the Core main class, it starts the program.

2
src/Main/SharpDevelop/Gui/SplashScreen.cs → src/Main/SharpDevelop/Startup/SplashScreen.cs

@ -6,7 +6,7 @@ using System.Collections.Generic; @@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
namespace ICSharpCode.SharpDevelop.Gui
namespace ICSharpCode.SharpDevelop.Startup
{
sealed class SplashScreenForm : Form
{

3
src/Main/SharpDevelop/Gui/Workbench/AvalonDockLayout.cs → src/Main/SharpDevelop/Workbench/AvalonDockLayout.cs

@ -12,8 +12,9 @@ using System.Windows.Media.Imaging; @@ -12,8 +12,9 @@ using System.Windows.Media.Imaging;
using AvalonDock;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
/// <summary>
/// Workbench layout using the AvalonDock library.

3
src/Main/SharpDevelop/Gui/Workbench/AvalonPadContent.cs → src/Main/SharpDevelop/Workbench/AvalonPadContent.cs

@ -9,8 +9,9 @@ using System.Windows.Threading; @@ -9,8 +9,9 @@ using System.Windows.Threading;
using AvalonDock;
using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
sealed class AvalonPadContent : DockableContent, IDisposable
{

3
src/Main/SharpDevelop/Gui/Workbench/AvalonWorkbenchWindow.cs → src/Main/SharpDevelop/Workbench/AvalonWorkbenchWindow.cs

@ -14,8 +14,9 @@ using System.Windows.Threading; @@ -14,8 +14,9 @@ using System.Windows.Threading;
using AvalonDock;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
sealed class AvalonWorkbenchWindow : DocumentContent, IWorkbenchWindow, IOwnerState
{

7
src/Main/SharpDevelop/Gui/Workbench/ChooseLayoutCommand.cs → src/Main/SharpDevelop/Workbench/ChooseLayoutCommand.cs

@ -4,11 +4,12 @@ @@ -4,11 +4,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using ICSharpCode.Core;
using System.Windows.Forms;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
/// <summary>
/// Command for layout combobox in toolbar.
@ -45,7 +46,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -45,7 +46,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
}
if (oldItem != editIndex && oldItem != resetIndex) {
WorkbenchSingleton.Workbench.WorkbenchLayout.StoreConfiguration();
SD.Workbench.WorkbenchLayout.StoreConfiguration();
}
if (comboBox.SelectedIndex == editIndex) {

146
src/Main/SharpDevelop/Workbench/DispatcherMessageLoop.cs

@ -0,0 +1,146 @@ @@ -0,0 +1,146 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Threading;
namespace ICSharpCode.SharpDevelop.Workbench
{
sealed class DispatcherMessageLoop : IMessageLoop, ISynchronizeInvoke
{
readonly Dispatcher dispatcher;
readonly SynchronizationContext synchronizationContext;
public DispatcherMessageLoop(Dispatcher dispatcher, SynchronizationContext synchronizationContext)
{
this.dispatcher = dispatcher;
this.synchronizationContext = synchronizationContext;
}
public Thread Thread {
get { return dispatcher.Thread; }
}
public Dispatcher Dispatcher {
get { return dispatcher; }
}
public SynchronizationContext SynchronizationContext {
get { return synchronizationContext; }
}
public ISynchronizeInvoke SynchronizingObject {
get { return this; }
}
public bool InvokeRequired {
get { return !dispatcher.CheckAccess(); }
}
public bool CheckAccess()
{
return dispatcher.CheckAccess();
}
public void VerifyAccess()
{
dispatcher.VerifyAccess();
}
public void InvokeIfRequired(Action callback)
{
if (dispatcher.CheckAccess())
callback();
else
dispatcher.Invoke(callback);
}
public void InvokeIfRequired(Action callback, DispatcherPriority priority)
{
if (dispatcher.CheckAccess())
callback();
else
dispatcher.Invoke(callback, priority);
}
public void InvokeIfRequired(Action callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
if (dispatcher.CheckAccess())
callback();
else
dispatcher.Invoke(callback, priority, cancellationToken);
}
public T InvokeIfRequired<T>(Func<T> callback)
{
if (dispatcher.CheckAccess())
return callback();
else
return dispatcher.Invoke(callback);
}
public T InvokeIfRequired<T>(Func<T> callback, DispatcherPriority priority)
{
if (dispatcher.CheckAccess())
return callback();
else
return dispatcher.Invoke(callback, priority);
}
public T InvokeIfRequired<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
if (dispatcher.CheckAccess())
return callback();
else
return dispatcher.Invoke(callback, priority, cancellationToken);
}
public Task InvokeAsync(Action callback)
{
return dispatcher.InvokeAsync(callback).Task;
}
public Task InvokeAsync(Action callback, DispatcherPriority priority)
{
return dispatcher.InvokeAsync(callback, priority).Task;
}
public Task InvokeAsync(Action callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
return dispatcher.InvokeAsync(callback, priority, cancellationToken).Task;
}
public Task<T> InvokeAsync<T>(Func<T> callback)
{
return dispatcher.InvokeAsync(callback).Task;
}
public Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority)
{
return dispatcher.InvokeAsync(callback, priority).Task;
}
public Task<T> InvokeAsync<T>(Func<T> callback, DispatcherPriority priority, CancellationToken cancellationToken)
{
return dispatcher.InvokeAsync(callback, priority, cancellationToken).Task;
}
IAsyncResult ISynchronizeInvoke.BeginInvoke(Delegate method, object[] args)
{
return dispatcher.InvokeAsync<object>(() => method.DynamicInvoke(args)).Task;
}
object ISynchronizeInvoke.EndInvoke(IAsyncResult result)
{
return ((Task<object>)result).Result;
}
object ISynchronizeInvoke.Invoke(Delegate method, object[] args)
{
return dispatcher.Invoke(() => method.DynamicInvoke(args));
}
}
}

61
src/Main/SharpDevelop/Workbench/FileService.cs

@ -0,0 +1,61 @@ @@ -0,0 +1,61 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.IO;
using System.Text;
using System.Threading;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Core;
using ICSharpCode.NRefactory.Editor;
using ICSharpCode.SharpDevelop.Editor;
namespace ICSharpCode.SharpDevelop.Workbench
{
sealed class FileService : IFileService
{
public Encoding DefaultFileEncoding {
get {
return Encoding.GetEncoding(SharpDevelop.FileService.DefaultFileEncodingCodePage);
}
}
public ITextSource GetFileContent(FileName fileName)
{
return GetFileContentForOpenFile(fileName) ?? GetFileContentFromDisk(fileName, CancellationToken.None);
}
public ITextSource GetFileContent(string fileName)
{
return GetFileContent(FileName.Create(fileName));
}
public ITextSource GetFileContentForOpenFile(FileName fileName)
{
return SD.MainThread.InvokeIfRequired(
delegate {
OpenedFile file = SharpDevelop.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
return new StringTextSource(FileReader.ReadFileContent(s, DefaultFileEncoding));
}
}
return null;
});
}
public ITextSource GetFileContentFromDisk(FileName fileName, CancellationToken cancellationToken)
{
return new StringTextSource(FileReader.ReadFileContent(fileName, DefaultFileEncoding));
}
}
}

2
src/Main/SharpDevelop/Gui/Workbench/FullScreenEnabledWindow.cs → src/Main/SharpDevelop/Workbench/FullScreenEnabledWindow.cs

@ -6,7 +6,7 @@ using System.Windows; @@ -6,7 +6,7 @@ using System.Windows;
using System.Windows.Forms;
using System.Windows.Interop;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
using WindowState = System.Windows.WindowState;

9
src/Main/SharpDevelop/Gui/Workbench/LayoutConfiguration.cs → src/Main/SharpDevelop/Workbench/LayoutConfiguration.cs

@ -8,7 +8,7 @@ using System.Xml; @@ -8,7 +8,7 @@ using System.Xml;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
class LayoutConfiguration
{
@ -122,11 +122,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -122,11 +122,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
return currentLayoutName;
}
set {
if (WorkbenchSingleton.InvokeRequired)
throw new InvalidOperationException("Invoke required");
SD.MainThread.VerifyAccess();
if (value != CurrentLayoutName) {
currentLayoutName = value;
WorkbenchSingleton.Workbench.WorkbenchLayout.LoadConfiguration();
SD.Workbench.WorkbenchLayout.LoadConfiguration();
OnLayoutChanged(EventArgs.Empty);
}
}
@ -135,7 +134,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -135,7 +134,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
public static void ReloadDefaultLayout()
{
currentLayoutName = DefaultLayoutName;
WorkbenchSingleton.Workbench.WorkbenchLayout.LoadConfiguration();
SD.Workbench.WorkbenchLayout.LoadConfiguration();
OnLayoutChanged(EventArgs.Empty);
}

3
src/Main/SharpDevelop/Gui/Workbench/SDStatusBar.cs → src/Main/SharpDevelop/Workbench/SDStatusBar.cs

@ -11,8 +11,9 @@ using System.Windows.Media.Imaging; @@ -11,8 +11,9 @@ using System.Windows.Media.Imaging;
using System.Windows.Shell;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
class SDStatusBar : StatusBar
{

15
src/Main/SharpDevelop/Gui/Workbench/SingleInstanceHelper.cs → src/Main/SharpDevelop/Workbench/SingleInstanceHelper.cs

@ -11,7 +11,7 @@ using System.Windows.Forms; @@ -11,7 +11,7 @@ using System.Windows.Forms;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
static class SingleInstanceHelper
{
@ -68,15 +68,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -68,15 +68,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
return new IntPtr(RESULT_PROJECT_IS_OPEN);
} else {
try {
WorkbenchSingleton.SafeThreadAsyncCall(
delegate { NativeMethods.SetForegroundWindow(WorkbenchSingleton.MainWin32Window.Handle) ; }
);
SD.MainThread.InvokeAsync(
delegate { NativeMethods.SetForegroundWindow(SD.Workbench.MainWin32Window.Handle); }
).FireAndForget();
string tempFileName = Path.Combine(Path.GetTempPath(), "sd" + fileNumber + ".tmp");
foreach (string file in File.ReadAllLines(tempFileName)) {
WorkbenchSingleton.SafeThreadAsyncCall(
delegate(string openFileName) { FileService.OpenFile(openFileName); }
, file
);
SD.MainThread.InvokeAsync(
delegate { SharpDevelop.FileService.OpenFile(file); }
).FireAndForget();
}
} catch (Exception ex) {
LoggingService.Warn(ex);

5
src/Main/SharpDevelop/Gui/Workbench/StatusBarService.cs → src/Main/SharpDevelop/Workbench/StatusBarService.cs

@ -8,8 +8,9 @@ using System.Threading; @@ -8,8 +8,9 @@ using System.Threading;
using System.Windows;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
sealed class StatusBarService : IStatusBarService
{
@ -57,7 +58,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -57,7 +58,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
public IProgressMonitor CreateProgressMonitor(CancellationToken cancellationToken = default(CancellationToken))
{
ProgressCollector progress = new ProgressCollector(WorkbenchSingleton.Workbench.SynchronizingObject, cancellationToken);
ProgressCollector progress = new ProgressCollector(SD.MainThread.SynchronizingObject, cancellationToken);
AddProgress(progress);
return progress.ProgressMonitor;
}

20
src/Main/SharpDevelop/Gui/Workbench/WorkbenchStartup.cs → src/Main/SharpDevelop/Workbench/WorkbenchStartup.cs

@ -4,15 +4,16 @@ @@ -4,15 +4,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Threading;
using System.Windows.Interop;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Startup;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
/// <summary>
/// Runs workbench initialization.
@ -30,6 +31,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -30,6 +31,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
ComponentDispatcher.ThreadIdle -= ComponentDispatcher_ThreadIdle; // ensure we don't register twice
ComponentDispatcher.ThreadIdle += ComponentDispatcher_ThreadIdle;
LayoutConfiguration.LoadLayoutConfiguration();
SD.Services.AddService(typeof(IMessageLoop), new DispatcherMessageLoop(app.Dispatcher, SynchronizationContext.Current));
WorkbenchSingleton.InitializeWorkbench(new WpfWorkbench(), new AvalonDockLayout());
}
@ -54,7 +56,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -54,7 +56,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
if (loader != null) {
loader.Load(fullFileName);
} else {
FileService.OpenFile(fullFileName);
SharpDevelop.FileService.OpenFile(fullFileName);
}
} catch (Exception e) {
MessageService.ShowException(e, "unable to open file " + file);
@ -63,8 +65,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -63,8 +65,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
// load previous solution
if (!didLoadSolutionOrFile && PropertyService.Get("SharpDevelop.LoadPrevProjectOnStartup", false)) {
if (FileService.RecentOpen.RecentProject.Count > 0) {
ProjectService.LoadSolution(FileService.RecentOpen.RecentProject[0]);
if (SharpDevelop.FileService.RecentOpen.RecentProject.Count > 0) {
ProjectService.LoadSolution(SharpDevelop.FileService.RecentOpen.RecentProject[0]);
didLoadSolutionOrFile = true;
}
}
@ -81,14 +83,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -81,14 +83,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
NavigationService.ResumeLogging();
Parser.ParserService.StartParserThread();
((ParserService)SD.ParserService).StartParserThread();
// finally run the workbench window ...
app.Run(WorkbenchSingleton.MainWindow);
app.Run(SD.Workbench.MainWindow);
// save the workbench memento in the ide properties
try {
PropertyService.SetNestedProperties(workbenchMemento, WorkbenchSingleton.Workbench.CreateMemento());
PropertyService.SetNestedProperties(workbenchMemento, SD.Workbench.CreateMemento());
} catch (Exception e) {
MessageService.ShowException(e, "Exception while saving workbench state.");
}

29
src/Main/SharpDevelop/Gui/Workbench/WpfWorkbench.cs → src/Main/SharpDevelop/Workbench/WpfWorkbench.cs

@ -16,12 +16,15 @@ using System.Windows.Input; @@ -16,12 +16,15 @@ using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Navigation;
using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Parser;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Startup;
namespace ICSharpCode.SharpDevelop.Gui.Workbench
namespace ICSharpCode.SharpDevelop.Workbench
{
/// <summary>
/// Workbench implementation using WPF and AvalonDock.
@ -53,7 +56,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -53,7 +56,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
}
public System.Windows.Forms.IWin32Window MainWin32Window { get { return this; } }
public ISynchronizeInvoke SynchronizingObject { get; private set; }
public Window MainWindow { get { return this; } }
IntPtr System.Windows.Forms.IWin32Window.Handle {
@ -72,7 +74,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -72,7 +74,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
public WpfWorkbench()
{
this.SynchronizingObject = new WpfSynchronizeInvoke(this.Dispatcher);
SD.Services.AddService(typeof(IStatusBarService), new StatusBarService(statusBar));
InitializeComponent();
InitFocusTrackingEvents();
@ -123,12 +124,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -123,12 +124,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
AddHandler(Hyperlink.RequestNavigateEvent, new RequestNavigateEventHandler(OnRequestNavigate));
Project.ProjectService.CurrentProjectChanged += SetProjectTitle;
FileService.FileRemoved += CheckRemovedOrReplacedFile;
FileService.FileReplaced += CheckRemovedOrReplacedFile;
FileService.FileRenamed += CheckRenamedFile;
SharpDevelop.FileService.FileRemoved += CheckRemovedOrReplacedFile;
SharpDevelop.FileService.FileReplaced += CheckRemovedOrReplacedFile;
SharpDevelop.FileService.FileRenamed += CheckRenamedFile;
FileService.FileRemoved += FileService.RecentOpen.FileRemoved;
FileService.FileRenamed += FileService.RecentOpen.FileRenamed;
SharpDevelop.FileService.FileRemoved += SharpDevelop.FileService.RecentOpen.FileRemoved;
SharpDevelop.FileService.FileRenamed += SharpDevelop.FileService.RecentOpen.FileRenamed;
requerySuggestedEventHandler = new EventHandler(CommandManager_RequerySuggested);
CommandManager.RequerySuggested += requerySuggestedEventHandler;
@ -156,7 +157,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -156,7 +157,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
// catch exceptions - e.g. incorrectly installed mail client
}
} else {
FileService.OpenFile(e.Uri.ToString());
SharpDevelop.FileService.OpenFile(e.Uri.ToString());
}
}
@ -171,7 +172,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -171,7 +172,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
void CheckRemovedOrReplacedFile(object sender, FileEventArgs e)
{
foreach (OpenedFile file in FileService.OpenedFiles) {
foreach (OpenedFile file in SharpDevelop.FileService.OpenedFiles) {
if (FileUtility.IsBaseDirectory(e.FileName, file.FileName)) {
foreach (IViewContent content in file.RegisteredViewContents.ToArray()) {
// content.WorkbenchWindow can be null if multiple view contents
@ -189,13 +190,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -189,13 +190,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
void CheckRenamedFile(object sender, FileRenameEventArgs e)
{
if (e.IsDirectory) {
foreach (OpenedFile file in FileService.OpenedFiles) {
foreach (OpenedFile file in SharpDevelop.FileService.OpenedFiles) {
if (file.FileName != null && FileUtility.IsBaseDirectory(e.SourceFile, file.FileName)) {
file.FileName = new FileName(FileUtility.RenameBaseDirectory(file.FileName, e.SourceFile, e.TargetFile));
}
}
} else {
OpenedFile file = FileService.GetOpenedFile(e.SourceFile);
OpenedFile file = SharpDevelop.FileService.GetOpenedFile(e.SourceFile);
if (file != null) {
file.FileName = new FileName(e.TargetFile);
}
@ -593,7 +594,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -593,7 +594,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
}
Project.ProjectService.CloseSolution();
ParserService.StopParserThread();
((ParserService)SD.ParserService).StopParserThread();
restoreBoundsBeforeClosing = this.RestoreBounds;
@ -668,7 +669,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench @@ -668,7 +669,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Workbench
if (loader != null) {
FileUtility.ObservedLoad(new NamedFileOperationDelegate(loader.Load), file);
} else {
FileService.OpenFile(file);
SharpDevelop.FileService.OpenFile(file);
}
}
}

8
src/Main/SharpDevelop/Gui/Workbench/WpfWorkbench.xaml → src/Main/SharpDevelop/Workbench/WpfWorkbench.xaml

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
<gui:FullScreenEnabledWindow
x:Class = "ICSharpCode.SharpDevelop.Gui.Workbench.WpfWorkbench"
<wb:FullScreenEnabledWindow
x:Class = "ICSharpCode.SharpDevelop.Workbench.WpfWorkbench"
x:ClassModifier = "internal"
xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:core = "http://icsharpcode.net/sharpdevelop/core"
xmlns:gui = "clr-namespace:ICSharpCode.SharpDevelop.Gui.Workbench"
xmlns:wb = "clr-namespace:ICSharpCode.SharpDevelop.Workbench"
Title = "{core:Localize MainWindow.DialogName}"
WindowStartupLocation = "Manual"
Background = "{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
@ -21,4 +21,4 @@ @@ -21,4 +21,4 @@
<!-- Statusbar will be inserted here (index: Count-2) -->
<ContentPresenter Name="mainContent" />
</DockPanel>
</gui:FullScreenEnabledWindow>
</wb:FullScreenEnabledWindow>
Loading…
Cancel
Save